React路由中Protected Routes与Nested Routes搭配使用失效问题
问题根因
1. PrivateRoute实现存在缺陷
当前PrivateRoute只处理了children属性,完全没有兼容component、render两种传组件的方式,且Route中render属性优先级高于component,导致传入的component属性根本不会生效。同时直接读取document.cookie无法监听认证状态变化,登出后组件不会自动重渲染触发重定向。
2. 嵌套路由配置不完整
UserHome内的部分PrivateRoute没有传入要渲染的组件,即使鉴权通过也会渲染空内容。
3. 重复鉴权逻辑冗余
App层的/home路径已经经过PrivateRoute鉴权,能进入UserHome组件的都是已登录用户,内层子路由重复加PrivateRoute属于不必要的逻辑。
解决方案
第一步:修复PrivateRoute实现
兼容所有路由传参方式,优先从认证Context拿状态保证状态变化能触发重渲染:
import { useContext } from 'react' // 导入你自己的AuthContext,从ProvideAuth里导出 import { AuthContext } from '你的ProvideAuth文件路径' const PrivateRoute = ({ component: Component, render, children, ...rest }) => { // 从认证Context拿登录状态,替代直接读cookie,状态变化自动触发重渲染 const { isAuthenticated } = useContext(AuthContext) return ( <Route {...rest} render={(routeProps) => { if (!isAuthenticated) { // 重定向时带上当前路径,登录后可以跳回原页面 return <Redirect to={{ pathname: "/login", state: { from: routeProps.location } }} /> } // 兼容三种组件传入方式 if (Component) return <Component {...routeProps} /> if (render) return render(routeProps) return children }} /> ) }
如果暂时不想用Context,至少要明确判断指定的认证cookie,避免随便有个cookie就认为已登录:
const isAuthenticated = document.cookie.includes('你的认证cookie名,比如token=')
第二步:修正嵌套路由配置
如果不需要子路由单独做权限控制,直接把UserHome内的PrivateRoute换成普通Route即可,外层已经做了全局登录校验:
const UserHome = () => { const { url } = useRouteMatch(); return ( <Wrapper> <Header /> <Suspense fallback={<Loader />}> <Switch> <Route exact path={`${url}/feed`} component={Feed} /> <Route path={`${url}/search`} component={Search} /> {/* 补全对应组件 */} <Route path={`${url}/addUser`} component={AddUser} /> {/* 补全对应组件 */} <Route path={`${url}/notification`} component={Notification} /> {/* 补全对应组件 */} <Route path={`${url}/profile`} component={UserProfile} /> </Switch> </Suspense> <BottomNavbar /> </Wrapper> ); };
如果子路由需要单独做权限控制,再保留PrivateRoute,同时补全对应的组件属性即可。
内容的提问来源于stack exchange,提问作者Mukul Sharma
相关产品推荐
相关产品推荐

