React使用Switch和Route拆分双Layout时AdminLayout子组件不渲染问题
问题原因
你当前的Admin路由写法多嵌套了一层不必要的Route,内层Route没有拿到正确的路由匹配上下文,导致render函数未触发,所以子组件无法渲染。
修复方案
根据你的使用场景二选一即可:
方案1:简化写法(仅需单个Admin面板路由时使用)
直接去掉多余的嵌套Route,外层匹配路径后直接判断权限传入组件,修改路由代码如下:
return ( <LoadingOverlay active={loading} text={<Loading text={loadingText} />}> <Switch> <Route path="/AdminPanel" exact render={() => ( <AdminLayout> {!isEmpty(user) && user.role === "Admin" ? ( <AdminDashBoard /> ) : ( <Redirect to="/404" /> )} </AdminLayout> )} /> <Route path={["/"]}> <MainLayout> <Switch> {/* 原有MainLayout下的子路由保持不变 */} <Route path="/Archive" component={Archive} /> <Route path="/Course/:id" component={SingleCourse} /> <Route path="/DashBoard" component={DashBoard} /> <Route path="/Login" render={() => ( <UserGlobalState setLoading={setLoading}> <Login /> </UserGlobalState> )} /> <Route path="/Logout" render={() => isEmpty(user) ? ( <Redirect to="/" /> ) : ( <Logout setLoading={setLoading} /> ) } /> <Route path="/Register" render={() => isEmpty(user) ? ( <UserGlobalState setLoading={setLoading}> <Register /> </UserGlobalState> ) : ( <Redirect to="/" /> ) } /> <Route path="/" exact render={() => <HomePageCourses courses={indexCourses} />} /> <Route path="*" component={NotFound} /> </Switch> </MainLayout> </Route> </Switch> </LoadingOverlay> )
方案2:规范嵌套路由写法(后续需要扩展Admin子路由时使用)
参考MainLayout的路由结构,把Admin相关的子路由统一放到AdminLayout内部管理:
- 先修改外层路由代码:
<Switch> {/* 不要加exact,保证子路由可以匹配到/AdminPanel前缀 */} <Route path="/AdminPanel"> <AdminLayout /> </Route> {/* 原有MainLayout路由保持不变 */} </Switch>
- 再修改AdminLayout.jsx,在children的位置加入Switch和Admin子路由:
const AdminLayout = () => { const dispatch = useDispatch(); // 这里需要把user相关的状态引入AdminLayout,或者通过context获取 useEffect(() => { dispatch(getAllUsers()); }, []); return ( <Fragment> <Helmet> <title>AdminPanel</title> </Helmet> <Navbar /> <div className="wrapper"> <div className="container"> <div className="row"> <SideBar /> <div className="col-md-9"> <div className="content"> <Switch> <Route path="/AdminPanel" exact render={() => !isEmpty(user) && user.role === "Admin" ? ( <AdminDashBoard /> ) : ( <Redirect to="/404" /> ) } /> {/* 后续新增的Admin子路由比如/AdminPanel/Users都写在这里 */} </Switch> <div className="module"> {/* 原有Adjust Budget Range模块代码保持不变 */} <div className="module-head"> <h3>Adjust Budget Range</h3> </div> <div className="module-body"> <div className="form-inline clearfix"> <a href="#" className="btn pull-right"> Update </a> <label htmlFor="amount">Price range:</label> <input type="text" id="amount" className="input-" /> </div> <hr /> <div className="slider-range"></div> </div> </div> </div> </div> </div> </div> </div> <div className="footer"> <div className="container"> <b className="copyright">© 2021 Saeed RayatMoghadam </b>All rights reserved. </div> </div> </Fragment> ); };
额外排查点
- 可以在权限判断分支加console.log,确认是否是user状态异常导致走到了重定向分支
- 重定向路径要加前缀斜杠,写成
to="/404",避免相对路径跳转异常
内容的提问来源于stack exchange,提问作者Saeed RayatMoghadam
相关产品推荐
相关产品推荐

