ReactJS中Protected Route出现Too many re render错误,本地正常服务器报错
问题原因
核心是两个逻辑叠加形成了无限重定向:
localStorage.getItem(key)当key不存在时返回的是null,不是空字符串,你代码中判断localStorage.getItem('token') === '',对于首次访问的新用户(部署后新环境的localStorage为空),这个条件永远不成立。- 未登录用户访问任意受保护路由时,
ProtectedRoute会跳转到/login,但/login的判断条件不成立,又会触发跳转到/,两者循环跳转触发重渲染报错。本地环境因为你之前测试时可能存过空值的token、userId,所以判断刚好成立,不会触发循环。

解决步骤
1. 修正Main组件的路由逻辑
删掉Switch内login路由的条件渲染,改成统一的render判断,不要在Switch层级做条件渲染,避免逻辑混乱:
<Switch> <ProtectedRoute exact path ={["/home","/"]} component={Dashboard} /> <ProtectedRoute exact path ="/list" component={List} /> <ProtectedRoute exact path ="/item" component={Item} /> <ProtectedRoute exact path ="/item/:id" component={Item} /> {/* 单独处理login路由逻辑 */} <Route exact path="/login" render={(props) => { const token = localStorage.getItem('token') const userId = localStorage.getItem('userId') // 已登录就跳首页,未登录渲染登录页 return token && userId ? <Redirect to="/" /> : <Login {...props} /> }} /> </Switch>
2. 优化ProtectedRoute的判断逻辑
把取值转成布尔值,避免空值、null、undefined的判断歧义:
import React from "react"; import { Redirect, Route } from "react-router-dom"; function ProtectedRoute({ component: Component, ...restOfProps }) { const token = localStorage.getItem("token"); const userId = localStorage.getItem('userId'); return ( <Route {...restOfProps} render={(props) => // 转布尔值判断更稳妥 !!token && !!userId ? <Component {...props} /> : <Redirect to="/login" /> } /> ); } export default ProtectedRoute;
3. 清理冗余代码
Main组件的handleLogout方法里,你已经把state中的token、userId初始化注释掉了,不需要再调用setState更新这两个不存在的state,删除对应代码避免不必要的重渲染:
handleLogout(){ // 删掉下面两行没用的setState // this.setState({token: ''}) // this.setState({userId:'' }) localStorage.setItem('userId','') localStorage.setItem('token', ''); // 退出后跳转到登录页 window.location.href = '/login' }
4. 可选优化(提升体验)
登录成功后不要用window.location='/'刷新整页,可以用react-router提供的history方法跳转,修改Login组件的登录成功逻辑:
// login请求成功后 if (response.status === 200 && response.data.token !== '') { localStorage.setItem('token', response.data.token); localStorage.setItem('userId', response.data.userId); // 替换window.location='/' this.props.history.push('/') }
修改完即可解决无限重渲染问题,同时保留受保护路由和登录页的访问控制逻辑。
内容的提问来源于stack exchange,提问作者Chauhan Mukesh
相关产品推荐
相关产品推荐

