Home > Enterprise >  Render a 404 page on its own without any other components with React Router
Render a 404 page on its own without any other components with React Router

Time:10-11

I am working with [email protected] and I have the following code:

index.tsx

const container = document.getElementById("app")!;
const root = createRoot(container);

root.render(
  <React.StrictMode>
    <Provider store={store}>
      <BrowserRouter>
        <Routes>
          <Route path="/" element={<App />} />
          <Route path="*" element={<NotFound />} />
        </Routes>
      </BrowserRouter>
    </Provider>
  </React.StrictMode>
);

reportWebVitals();

And in my App.tsx I have:

const App = () => {
  return (
    <>
      <Sidebar />
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="patients/:patient" element={<Patient />}>
          <Route path="overview" element={<Overview />} />
        </Route>
      </Routes>
    </>
  );
};

export default App;

In the Chrome console, I get the following warning:

utils.ts:767 You rendered descendant <Routes> (or called `useRoutes()`) at "/" (under <Route path="/">) but the parent route path has no trailing "*". This means if you navigate deeper, the parent won't match anymore and therefore the child routes will never render.

Please change the parent <Route path="/"> to <Route path="*">.

Why am I getting this warning and what can I do to fix it?

I still get the warning even if I remove <Route path="/" element={<Home />} /> from my App.tsx

Right now, only the / routes works. It renders the <Sidebar /> and the <Home /> components. But if I go to http://localhost:3000/patients/blah/overview I get the <NotFound /> component when I should be getting the <Overview /> component (at least that's what I want to be getting)

CodePudding user response:

The App component is rendering descendent routes, so the parent route should append a trailing "*" wildcard matcher to its route.

Example:

const container = document.getElementById("app")!;
const root = createRoot(container);

root.render(
  <React.StrictMode>
    <Provider store={store}>
      <BrowserRouter>
        <Routes>
          <Route path="/*" element={<App />} />
          <Route path="*" element={<NotFound />} />
        </Routes>
      </BrowserRouter>
    </Provider>
  </React.StrictMode>
);

To handle "unknown" routes the descendent Routes component necessarily needs to render another NotFound route.

const App = () => {
  return (
    <>
      <Sidebar />
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="patients/:patient" element={<Patient />}>
          <Route path="overview" element={<Overview />} />
        </Route>
        <Route path="*" element={<NotFound />} />
      </Routes>
    </>
  );
};

If the App component is really only serving as a "layout route" to render the Sidebar component with specific routes then I suggest converting it to an actual layout route.

import { Outlet } from 'react-router-dom';

const AppLayout = () => {
  return (
    <>
      <Sidebar />
      <Outlet />
    </>
  );
};

...

const container = document.getElementById("app")!;
const root = createRoot(container);

root.render(
  <React.StrictMode>
    <Provider store={store}>
      <BrowserRouter>
        <Routes>
          <Route element={<AppLayout />}>
            <Route path="/" element={<Home />} />
              <Route path="patients/:patient" element={<Patient />}>
              <Route path="overview" element={<Overview />} />
            </Route>
          </Route>
          <Route path="*" element={<NotFound />} />
        </Routes>
      </BrowserRouter>
    </Provider>
  </React.StrictMode>
);
  • Related