【问题标题】:React router v6: catch all "*" path does not work when using nested routesReact router v6: catch all \"*\" path does not work when using nested routes
【发布时间】:2022-12-02 01:41:01
【问题描述】:

I have the following two files

AppRoutes.tsx

import { Route, Routes } from "react-router-dom";
import NotFound from "../pages/NotFound";
import MessageRoutes from "../features/messages/routes/MessageRoutes";
import Home from "../pages/Home";

export default function AppRoutes() {
  return (
    <Routes>
      <Route path="/" element={<Home />} />
      <Route path="/messages/*" element={<MessageRoutes />} />
      <Route path="*" element={<NotFound />} />
    </Routes>
  );
}

MessageRoutes.tsx

import { Route, Routes } from "react-router-dom";
import ProtectedRoutes from "../../../routes/ProtectedRoutes";
import MessageOverview from "../pages/MessageOverview";
import NewMessage from "../pages/NewMessage";

export default function MessageRoutes() {
  return (
    <Routes>
      <Route element={<ProtectedRoutes />}>
        <Route path="/" element={<MessageOverview />} />
        <Route path="/new" element={<NewMessage />} />
      </Route>
    </Routes>
  );
}

Because I'm using the path "/messages/*" to capture all paths that start with /messages, my MessageRoutes component takes care of these nested routes. I have a final "*" route in the AppRoutes component to capture any url that the app does not support. But if the path would be "/messages/loremipsum", react router does not catch the NotFound route because everything that starts with "/messages" will be handled with the MessageRoutes component.

Does this mean that in every nested route component I now have to add a final &lt;Route path="\*" element={\&lt;NotFound /\&gt;} /\&gt; again, just to support a final catch all route? I don't like this approach. Is there no absolute final catch all for every route?

【问题讨论】:

    标签: javascript reactjs react-router react-router-dom


    【解决方案1】:

    Does this mean that in every nested route component I now have to add a final &lt;Route path="*" element={&lt;NotFound /&gt;} &gt; again

    Yes, absolutely. Each Routes component manages its own "scope" of routes for what it can match. For example if the current URL path is "/messages/loremipsum" the root Routes component matches the "/messages/*" and correctly renders the MessageRoutes component. The MessageRoutes component's Routes component then works on matching on the next path segment. Since there is no "*/loremipsum" route path you need another "catch-all" route to handle this.

    The issue is that a Routes component isn't aware of whatdescendentroutes any of its routesmaypossibly be rendering.

    Example:

    import { Route, Routes } from "react-router-dom";
    import NotFound from "../pages/NotFound";
    import MessageRoutes from "../features/messages/routes/MessageRoutes";
    import Home from "../pages/Home";
    
    export default function AppRoutes() {
      return (
        <Routes>
          <Route path="/" element={<Home />} />
          <Route path="/messages/*" element={<MessageRoutes />} />
          <Route path="*" element={<NotFound />} />
        </Routes>
      );
    }
    
    import { Route, Routes } from "react-router-dom";
    import ProtectedRoutes from "../../../routes/ProtectedRoutes";
    import MessageOverview from "../pages/MessageOverview";
    import NewMessage from "../pages/NewMessage";
    import NotFound from "../pages/NotFound";
    
    export default function MessageRoutes() {
      return (
        <Routes>
          <Route element={<ProtectedRoutes />}>
            <Route path="/" element={<MessageOverview />} />
            <Route path="/new" element={<NewMessage />} />
            <Route path="*" element={<NotFound />} />
          </Route>
        </Routes>
      );
    }
    

    If you want to have a single "catch-all" route then you'll need to have a single routes configuration.

    Example:

    import { Route, Routes } from "react-router-dom";
    import MessageOverview from "../pages/MessageOverview";
    import NewMessage from "../pages/NewMessage";
    import NotFound from "../pages/NotFound";
    import Home from "../pages/Home";
    
    export default function AppRoutes() {
      return (
        <Routes>
          <Route path="/" element={<Home />} />
          <Route element={<ProtectedRoutes />}>
            <Route path="/messages">
              <Route index element={<MessageOverview />} />
              <Route path="new" element={<NewMessage />} />
            </Route>
          </Route>
          <Route path="*" element={<NotFound />} />
        </Routes>
      );
    }
    

    Now when/if the URL path is "/messages/loremipsum" thenthisRoutes component knows whatnestedroutes it is rendering and can match and can correctly render NotFound.

    【讨论】:

      猜你喜欢
      • 2022-12-27
      • 2016-12-29
      • 1970-01-01
      • 2021-07-19
      • 2022-12-02
      • 2018-12-07
      • 2022-01-17
      • 2022-12-27
      • 2021-08-11
      相关资源
      最近更新 更多