ReactJS中基于用户认证状态跳转路由的推荐实现方式咨询
你现在的实现已经能满足基础需求,但确实有几个可以优化的点,也有更工程化的实现方式:
现有实现的不足
- 鉴权逻辑分散在每个页面组件里,后续新增页面需要重复写重定向判断,维护成本高
- 初始化
isLoggedin状态时默认设为false,等到componentDidMount才读取本地存储更新状态,已经登录的用户访问页面时会出现短暂的登录页闪屏再跳首页的问题 - 你当前写的
/login路由的render属性传值有语法问题,render需要接收一个返回组件的函数,你写的render={<Login isLoggedin={this.state.isLoggedin} />}会直接报错
推荐实现方案
我们可以通过封装自定义鉴权路由组件的方式收拢所有鉴权逻辑,后续新增路由直接复用即可,无需每个页面单独写判断。
1. 封装公共路由组件
// 需要登录才能访问的受保护路由 const ProtectedRoute = ({isLoggedin, component: Component, ...rest}) => { return ( <Route {...rest} render={props => isLoggedin ? <Component {...props} /> : <Redirect to="/login" /> } /> ) } // 仅未登录用户能访问的公开路由(比如登录页、注册页) const PublicRoute = ({isLoggedin, component: Component, ...rest}) => { return ( <Route {...rest} render={props => !isLoggedin ? <Component {...props} /> : <Redirect to="/home" /> } /> ) }
2. 优化App组件的状态初始化与路由配置
class App extends React.Component{ constructor(props){ super(props); // 初始化直接读取本地存储,避免挂载后更新状态导致的闪屏 this.state={ isLoggedin: !!localStorage.getItem('name') } } render(){ return( <> <Switch> <PublicRoute exact path="/" isLoggedin={this.state.isLoggedin} component={Login} /> <PublicRoute exact path="/login" isLoggedin={this.state.isLoggedin} component={Login} /> <ProtectedRoute exact path="/home" isLoggedin={this.state.isLoggedin} component={Home} /> </Switch> </> ); } }
3. 简化业务页面代码
因为鉴权逻辑已经放到了路由层,Login和Home组件不需要再写重定向逻辑:
// Login.js class Login extends React.Component{ render(){ return <h1>Login here</h1>; } } // Home.js class Home extends React.Component{ render(){ return <h1>Home</h1>; } }
优化收益
- 逻辑复用:所有鉴权逻辑统一维护,后续新增页面只需要选择用
ProtectedRoute还是PublicRoute包裹即可,无需重复编写重定向代码 - 无闪屏体验:初始化状态直接读取本地存储,不会出现登录用户访问时先闪登录页的问题
- 可扩展性强:后续如果需要修改鉴权规则,比如增加token过期校验、权限判断,只需要修改
ProtectedRoute和PublicRoute的代码即可,不需要改动业务页面
内容的提问来源于stack exchange,提问作者Gratis Devs
相关产品推荐
相关产品推荐

