Handling /news vs /news/:id in React Router v7 Without Breaking Nested Routes

Handling /news vs /news/:id in React Router v7 Without Breaking Nested Routes
Photo by Stefan Gessert / Unsplash

When working with React Router v7, a common scenario arises where you want /news itself to return a 404, while still keeping nested routes like /news/id/5 fully functional.

If you’re coming from v6, the good news is that v7 uses the same nested route structure, so the approach remains largely the same. Let’s walk through this step by step.


The Core Problem

If you only define:

<Route path="/news/*" element={<NewsRoutes />} />
  • /news → Matches and renders NewsRoutes (not what you want).
  • /news/id/5 → Works fine.

If you comment it out:

{/* <Route path="/news/*" element={<NewsRoutes />} /> */}

then both /news and /news/id/5 break, because the router no longer has a rule for those paths.


The Correct Approach in v7: Nested Route Definitions

The key is to define /news as a parent route and handle the base path (/news) separately from its nested paths:

<Route path="/news">
  <Route index element={<NotFound />} /> {/* Handles /news */}
  <Route path="*" element={<NewsRoutes />} /> {/* Handles /news/* */}
</Route>

How it works:

  • /news → Hits the index child, showing a 404 Not Found (or whatever fallback you define).
  • /news/id/5 → Falls through to the * child, rendering your NewsRoutes component.

This pattern ensures /news doesn’t load content incorrectly, while /news/:id and other dynamic routes still behave properly.


Example With a Reusable 404 Component

You’ll usually want a central 404 component:

function NotFound() {
  return <h2>404 - Page Not Found</h2>;
}

<Route path="/news">
  <Route index element={<NotFound />} />
  <Route path="*" element={<NewsRoutes />} />
</Route>

React Router v7 Notes

  • Same API as v6 for nested routes → v7 focuses on performance, data APIs, and React 18+ features, but the route definition syntax hasn’t changed, so the solution applies directly.
  • createRoutesFromElements and createBrowserRouter still work with this structure if you’re using data routers.
  • You can still use <Navigate> for redirects (e.g., redirect /news to /news/latest instead of showing 404).

Other Considerations

  1. SEO Implications
    • /news returning a 404 is correct if it’s not a real page.
    • If you want Google to index /news as a category page, don’t use this setup—serve a landing page instead.
  2. User Experience
    • This is often friendlier for users if /news doesn’t stand on its own.
  3. Testing
    Be sure to test all cases:
    • /news → 404 (or redirect)
    • /news/id/5 → Works
    • /news/unknown → Handled by NewsRoutes logic
    • Unrelated routes → Still follow your global route rules
  4. Future-Proofing
    If later you want /news to show a list of articles, just swap out the NotFound with a NewsLandingPage component—no breaking changes to nested routes.

Global 404 Catch-All
At the bottom of your routes, you’ll typically define:

<Route path="*" element={<NotFound />} />

You can reuse the same NotFound component inside /news for consistency.

Instead of a 404, you may prefer a redirect:

<Route path="/news">
  <Route index element={<Navigate to="/home" replace />} />
  <Route path="*" element={<NewsRoutes />} />
</Route>

Finally

With React Router v7, handling /news differently from /news/:id is simple:

  • Use an index route for the base /news.
  • Use a wildcard child route for /news/*.

This gives you precise control, keeps nested routes working, and avoids SEO or UX pitfalls. The pattern is identical to v6, so you don’t need to relearn anything—just apply it consistently across your app.

Support Us

Share to Friends