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

React使用Context实现登录跳转时报未挂载组件状态更新错误如何处理

错误原因

该警告由已卸载组件的状态更新触发,执行流程如下:

  1. 登录接口请求成功后进入回调函数,首先调用Auth.logIn()更新AuthProvider的全局状态,isAuthenticated变为true
  2. 路由层ProtectedLogin组件检测到登录态变更,直接触发重定向到/home,LoginForm、LoginPage组件被立即卸载
  3. 回调后续执行setRedirect(true)更新LoginForm的本地状态,此时组件已被卸载,触发警告

修复方案

方案1(最优):移除冗余的重定向逻辑

你的路由层已经配置了登录态校验逻辑:已登录用户访问登录页会自动跳转到首页,不需要在LoginForm内单独维护redirect状态控制跳转,直接删除冗余代码即可。
修改后的login-form.component.tsx核心代码:

const LoginForm = () => {
  const Auth = React.useContext(AuthContext);

  return (
    <Formik
      initialValues={{ email: "", password: "" }}
      onSubmit={(formValues: FormikValues) => {
        ApiService.post("user/authenticate", formValues)
          .then((res: any) => {
            Auth.logIn({token: res.token});
            Auth.initTokenChecking();
            // 移除setRedirect调用,路由层会自动处理跳转
          })
          .catch(() => console.log('error'));
      }}
      validationSchema={Yup.object().shape({
        email: Yup.string(),
        password: Yup.string()
      })}
    >
      {/* 其余Formik渲染逻辑保持不变 */}
    </Formik>
  );
};

export default LoginForm;

方案2(可选):添加组件挂载状态检测

如果需要保留LoginForm内的重定向逻辑,可以添加挂载状态标记,避免更新已卸载组件的状态:

const LoginForm = () => {
  const [redirect, setRedirect] = useState(false);
  const Auth = React.useContext(AuthContext);
  const isMounted = useRef(true);

  useEffect(() => {
    return () => {
      isMounted.current = false;
    }
  }, []);

  if (redirect) {
    return <Redirect to="/home" />;
  }

  return (
    <Formik
      initialValues={{ email: "", password: "" }}
      onSubmit={(formValues: FormikValues) => {
        ApiService.post("user/authenticate", formValues)
          .then((res: any) => {
            Auth.logIn({token: res.token});
            Auth.initTokenChecking();
            if (isMounted.current) {
              setRedirect(true);
            }
          })
          .catch(() => console.log('error'));
      }}
      // 其余配置保持不变
    >
      {/* 其余渲染逻辑保持不变 */}
    </Formik>
  );
};

附加优化:避免重复创建定时器

当前initTokenChecking方法每次登录都会新建定时器,重复登录会导致多个定时器同时运行,同时未处理token不存在时的解码报错,建议修改为:

initTokenChecking = () => {
  // 先清理已有定时器,避免重复创建
  if (this._interval) {
    clearInterval(this._interval);
  }
  this._interval = setInterval(() => {
    if (!localStorage.getItem("token")) {
      this.logOut();
      return; // 无token直接返回,避免后续解码报错
    }
    const token = JSON.parse(localStorage.getItem("token"));
    console.log(jwt_decode(token));
    if (jwt_decode(token).exp < Date.now() / 1000) {
      this.logOut();
    }
  }, 2 * 60 * 1000);
};

内容的提问来源于stack exchange,提问作者K.W.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 16:57:00