React Router V5多布局渲染问题:AuthLayout无法加载
解决React双布局路由匹配问题
你的问题核心是外层<Switch>里的两个<Route>都没有设置path属性,根据React Router规则,未指定path的Route会匹配任意路径,所以第一个包裹MainLayout的Route会被优先渲染,导致AuthLayout对应的Route永远不会被触发。访问/login时,进入MainLayout后内部Switch找不到匹配的路由,因此显示空白的MainLayout。
以下是两种无需修改现有路径的解决方法:
方法一:为外层Route指定匹配路径数组
React Router v5支持path接收数组,直接为两个外层Route分别配置对应布局下的所有路径:
<div className="App"> <Provider store={store}> <BrowserRouter> <Switch> {/* MainLayout 匹配的路径集合 */} <Route path={[ "/", "/search", "/user/:user_id", "/settings", "/communities", "/communities/new", "/communities/view/:community_id", "/communities/edit/:community_id", "/404" ]}> <MainLayout> <Switch> <Route path="/" exact component={Dashboard} /> <Route path="/search" exact component={SearchResults} /> <Route path="/user/:user_id" exact component={Profile} /> <PrivateRoute path="/settings" exact component={Settings} /> <Route path="/communities" exact component={CommunityDashboard} /> <PrivateRoute path="/communities/new" exact component={CommunityNew} /> <Route path="/communities/view/:community_id" exact component={CommunityView} /> <PrivateRoute path="/communities/edit/:community_id" exact component={CommunityEdit} /> <Route path='/404' component={Error404} /> </Switch> </MainLayout> </Route> {/* AuthLayout 匹配的路径集合 */} <Route path={["/password-reset/:reset_key?", "/register", "/login"]}> <AuthLayout> <Switch> <Route path="/password-reset/:reset_key?" exact component={PasswordReset} /> <Route path="/register" exact component={Register} /> <Route path="/login" exact component={Login} /> </Switch> </AuthLayout> </Route> <Redirect from='*' to='/404' /> </Switch> </BrowserRouter> </Provider> </div>
方法二:用matchPath动态判断布局(更简洁)
借助useLocation和matchPath钩子,动态判断当前路径所属布局,避免手动维护路径数组:
import { useLocation, matchPath } from 'react-router-dom'; // 定义两组路径的匹配规则 const mainLayoutPaths = [ "/", "/search", "/user/:user_id", "/settings", "/communities", "/communities/new", "/communities/view/:community_id", "/communities/edit/:community_id", "/404" ]; const authLayoutPaths = ["/password-reset/:reset_key?", "/register", "/login"]; function App() { const location = useLocation(); // 判断当前路径是否匹配MainLayout规则 const isMainLayout = mainLayoutPaths.some(path => matchPath(location.pathname, { path, exact: true }) ); // 判断当前路径是否匹配AuthLayout规则 const isAuthLayout = authLayoutPaths.some(path => matchPath(location.pathname, { path, exact: true }) ); return ( <div className="App"> <Provider store={store}> <BrowserRouter> {isMainLayout ? ( <MainLayout> <Switch> <Route path="/" exact component={Dashboard} /> <Route path="/search" exact component={SearchResults} /> <Route path="/user/:user_id" exact component={Profile} /> <PrivateRoute path="/settings" exact component={Settings} /> <Route path="/communities" exact component={CommunityDashboard} /> <PrivateRoute path="/communities/new" exact component={CommunityNew} /> <Route path="/communities/view/:community_id" exact component={CommunityView} /> <PrivateRoute path="/communities/edit/:community_id" exact component={CommunityEdit} /> <Route path='/404' component={Error404} /> </Switch> </MainLayout> ) : isAuthLayout ? ( <AuthLayout> <Switch> <Route path="/password-reset/:reset_key?" exact component={PasswordReset} /> <Route path="/register" exact component={Register} /> <Route path="/login" exact component={Login} /> </Switch> </AuthLayout> ) : ( <Redirect to='/404' /> )} </BrowserRouter> </Provider> </div> ); }
两种方法都能在不修改现有路径的前提下实现双布局正常渲染,方法二更适合路径较多的场景,后续新增路径只需更新对应规则数组即可。
内容的提问来源于stack exchange,提问作者Sam Munroe
相关产品推荐
相关产品推荐

