You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Router登录认证后重定向 添加location state触发无限渲染问题

问题根因及修复方案

1. 修复路由配置结构错误

你当前把/login路由定义在了<Switch>标签外部,会导致每次路由匹配都会先触发Login路由的渲染逻辑,和内部PrivateRoute的重定向逻辑形成冲突,修改配置如下:

<Router history={history}>
  <ThemeProvider theme={theme}>
    <CssBaseline />
    <Alert th={ui.darkTheme} />
    <UpdateApp />
    <Switch>
      {/* 把login路由移到Switch最顶部 */}
      <Route path="/login" exact component={Login} />
      <PrivateRoute path="/" exact component={Homepage} />
      <PrivateRoute path="/info" exact component={Infos} />
      <PrivateRoute path="/info/add" exact component={AddInfo} />
      <PrivateRoute path="/info/:id" exact component={ShowInfo} />
      <PrivateRoute path="/info/:id/edit" exact component={EditInfo} />
      <PrivateRoute component={Four} />
    </Switch>
  </ThemeProvider>
</Router>

2. 给useSelector添加浅层对比避免不必要重渲染

默认useSelector用严格等于(===)判断返回值是否变化,如果你Redux里更新auth状态时每次返回新对象,哪怕属性值完全没变也会触发PrivateRoute重渲染,修改如下:

// 从react-redux导入shallowEqual
import { shallowEqual, useSelector } from 'react-redux';

// 修改useSelector调用
const auth = useSelector((state: RootState) => state.auth, shallowEqual);

3. 优化Redirect的to对象引用

你当前在render函数里直接写对象字面量作为to参数,每次render都会生成新的对象,触发Redirect重复执行重定向逻辑,用useMemo缓存from的值即可:

const PrivateRoute = ({ component: Component, exact, path, }: RouteProps): JSX.Element => {
  if (!Component) return <div />;
  const classes = useStyles();
  const auth = useSelector((state: RootState) => state.auth, shallowEqual);
  
  return (
    <Route 
      path={path} 
      exact={exact} 
      render={(props) => {
        if (auth.loading) {
          return (
            <Backdrop className={classes.backdrop} open>
              <CircularProgress color="inherit" />
            </Backdrop>
          )
        }
        if (auth.isAuthenticated) {
          return <Component {...props} />
        }
        // 只有props.location变化时才生成新的to对象
        const redirectTo = useMemo(() => ({
          pathname: '/login',
          state: { from: props.location }
        }), [props.location])
        return <Redirect to={redirectTo} />
      }} 
    />
  );
};

4. 校验Login组件的跳转逻辑

确认登录成功后的跳转逻辑不会重复触发重定向,参考写法如下:

// Login组件登录成功后的跳转逻辑
const handleLogin = async () => {
  // 调用登录接口,更新Redux的auth状态
  await requestLogin(loginForm);
  dispatch(updateAuth({ isAuthenticated: true, loading: false }));
  // from值判空,默认跳首页,避免空值报错
  const targetPath = location.state?.from?.pathname || '/';
  // 用replace替代push,避免用户点后退回到登录页
  history.replace(targetPath);
}

完成以上修改即可解决无限渲染循环问题。

内容的提问来源于stack exchange,提问作者lulu33

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 22:42:02