[英]Nested routes and not found route in react router dom v5
While trying to make nested routes in react router dom v5 I found this answer that explains how to do it very well在尝试在反应路由器 dom v5 中创建嵌套路由时,我发现这个答案解释了如何很好地做到这一点
(please take a look at the code here because it's a little bit difference from the answer mentioned above) (请看这里的代码,因为它与上面提到的答案有点不同)
const NotFound = () => <h1>Not Found</h1>;
function Layouts() {
return (
<Switch>
<Route path="/auth" component={AuthLayout} />
<Route path="/app" component={AppLayout} />
<Route path="/" component={NotFound} />
</Switch>
);
}
const Signup = () => <p>Login</p>;
const Login = () => <p>Sign up</p>;
function AuthLayout() {
return (
<div>
<h1>Auth Layout</h1>
<Route path="/auth/signup" exact component={Signup} />
<Route path="/auth/login" exact component={Login} />
{/* Commenting this because I want to go to NotFound component */}
{/* <Redirect from="/auth" to="/auth/login" exact /> */}
</div>
);
}
const Home = () => <p>Home</p>;
const Dashboard = () => <p>Dashboard</p>;
function AppLayout() {
return (
<div>
<h1>App Layout</h1>
<Route path="/app/home" exact component={Home} />
<Route path="/app/dashboard" exact component={Dashboard} />
{/* Commenting this because I want to go to NotFound component */}
{/* Redirect from="/app" to="/app/home" exact /> */}
</div>
);
}
But this have one problem, that if you go to a route with /app/somethingnotfound
it won't go to <Route path="/" component={NotFound} />
, it will "stay inside" AppLayout
and render no route.但这有一个问题,如果你 go 到带有
/app/somethingnotfound
的路由,它不会 go 到<Route path="/" component={NotFound} />
,它将“留在里面” AppLayout
并且不渲染路由.
How can I make /app/somethingnotfound
go to <Route path="/" component={NotFound} />
in this case?在这种情况下,如何将
/app/somethingnotfound
go 设置为<Route path="/" component={NotFound} />
?
Just to be more clear: I don't want to just add <Route component={NotFound} />
inside AuthLayout
and AppLayout
because it will render other things.更清楚一点:我不想在
AuthLayout
和AppLayout
中添加<Route component={NotFound} />
因为它会渲染其他东西。 What I really need is to show the top level NotFound
.我真正需要的是展示顶级
NotFound
。
Not found component usually works like this:未找到的组件通常是这样工作的:
<Router>
<Switch>
<Route exact path="/auth" component={AuthLayout} />
<Route exact path="/app" component={AppLayout} />
<Route component={NotFound} />
</Switch>
</Router>
But you cannot mark /auth
and /app
as exact
as they contain nested routes.但是您不能将
/auth
和/app
标记为exact
,因为它们包含嵌套路由。 So, you should do:所以,你应该这样做:
<Router>
<Switch>
<Route path="/auth" component={AuthLayout} />
<Route path="/app" component={AppLayout} />
<Route exact path="/404" component={NotFound} />
<Redirect to='/404' />
</Switch>
</Router>
and your component (eg AppLayout
) with nested routes:以及带有嵌套路由的组件(例如
AppLayout
):
<>
<h1>App Layout</h1>
<Switch>
<Route path="/app/home" exact component={Home} />
<Route path="/app/dashboard" exact component={Dashboard} />
<Redirect to="/404" />
</Switch>
</>
While looking in github issues I found out this solution , you create a "global not found page" where you pass through the state if the route isn't found, and just render that instead of the other routes.在查看 github 问题时,我发现了这个解决方案,您创建了一个“全局未找到页面”,如果找不到路由,则在其中通过 state,然后只渲染它而不是其他路由。
const NotFound = () => <div className="not_found"><h1>Not Found</h1></div>;
const RouteNotFound = () => <Redirect to={{ state: { notFoundError: true } }} />;
const CaptureRouteNotFound = withRouter(({children, location}) => {
return location && location.state && location.state.notFoundError ? <NotFound /> : children;
});
const Settings = () => {
return (
<Switch>
<Route path="/settings/account" render={() => <h1>Account Settings</h1>} />
<Route path="/settings/profile" render={() => <h1>Profile Settings</h1>} />
<RouteNotFound />
</Switch>
);
};
const AppShell = ({children}) => {
return (
<div className="application">
<header>Application</header>
{children}
</div>
);
};
const Application = () => {
return (
<Router>
<CaptureRouteNotFound>
<AppShell>
<Switch>
<Route path="/settings" render={() => <Settings />} />
<Route path="/profile" render={() => <h1>User Profile</h1>} />
<RouteNotFound />
</Switch>
</AppShell>
</CaptureRouteNotFound>
</Router>
);
};
<Route path="/" component={NotFound} />
doesn't match for all the nested that are not implemented, because the Switch
in the Layouts
component will only render the first Route
child that matches the pathname
. <Route path="/" component={NotFound} />
不匹配所有未实现的嵌套,因为Layouts
组件中的Switch
只会渲染与pathname
匹配的第一个Route
子节点。 In your case, it matches the route with AppLayout
component when you go the path /app/somethingdoesntexist
that is why it only renders the AppLayout
component.在您的情况下,当您 go 路径
/app/somethingdoesntexist
时,它将路由与AppLayout
组件匹配,这就是它仅呈现AppLayout
组件的原因。
Solution解决方案
It is better to implement a NotFound
route for each layout using nested Switch
components, For example最好使用嵌套的
Switch
组件为每个布局实现NotFound
路由,例如
function AppLayout() {
const { path, url } = useRouteMatch();
return (
<Switch>
<Route path={`${path}/home`} exact component={Home} />
<Route path={`${path}/dashboard`} exact component={Dashboard} />
<Route path="*" component={NotFound} />
</Switch>
);
}
In the case above we got the matched path by using useRouteMatch
hook and nest another Switch
component that will render any nested route that matches from the path
and we provide a fallback Route
specifying the path as "*"
which will render the NotFound
component when there is no match found.在上面的例子中,我们通过使用
useRouteMatch
钩子获得了匹配的路径,并嵌套了另一个Switch
组件,该组件将渲染与path
匹配的任何嵌套路由,并且我们提供了一个备用Route
,将路径指定为"*"
,它将在存在时渲染NotFound
组件没有找到匹配项。
Here is a complete example of the solution codesandbox .这是解决方案代码框的完整示例。
You can also see the nesting example provided in the docs.您还可以查看文档中提供的嵌套示例。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.