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

如何修复React报错:Can't perform state update on unmounted component

问题修复方案

根因分析

触发警告和异常的核心原因有3个:

  1. App组件内的异步请求没有添加清理逻辑,若组件卸载时请求仍在进行,后续dispatch操作会触发「卸载组件更新状态」的警告
  2. 登录状态更新顺序错误:先将isLogged设为true触发Home组件渲染,再请求用户信息,导致Home组件初始渲染时auth.user为空数组,直接取auth.user[0].username会出现取值异常
  3. Home组件没有做空值兼容,auth.user为空时直接索引取值会抛出隐性错误,也会连带触发状态更新异常警告

具体修复步骤

1. 修正App.tsx的异步逻辑与清理机制

调整登录状态更新顺序,同时为异步请求添加卸载清理逻辑,避免无效dispatch:

function App() {
  const dispatch = useDispatch();
  const auth = useSelector((state: RootStateOrAny) => state.auth);
  const token = useSelector((state: RootStateOrAny) => state.token);

  useEffect(() => {
    // 添加请求取消控制器,组件卸载时终止未完成的请求
    const controller = new AbortController();
    const firstlogin = localStorage.getItem('firstlogin');

    if(firstlogin) {
      const getUserToken = async () => {
        try {
          const res: any = await axios.post('/user/refresh_token', null, {
            signal: controller.signal
          });
          dispatch({type: "GET_TOKEN", payload: res.data.access_token});
        } catch (err) {
          // 忽略取消请求的报错
          if (axios.isCancel(err)) return;
        }
      };
      getUserToken();
    }
    // 清理函数:组件卸载时终止请求
    return () => controller.abort();
  }, [auth.isLogged, dispatch]);

  useEffect(() => {
    // 标记组件是否挂载,避免卸载后执行dispatch
    let isMounted = true;
    if(token){
      const getUser = async () => {
        try {
          // 先请求用户信息,请求成功再更新登录状态
          const res = await fetchUser(token);
          if (isMounted) {
            dispatch(dispatchGetUser(res));
            dispatch(dispatchLogin());
          }
        } catch (err) {
          // 可在这里添加token过期的清理逻辑,比如清空本地存储跳登录页
        }
      }
      getUser();
    }
    // 清理函数:标记组件已卸载
    return () => { isMounted = false };
  },[token, dispatch]);

  return (
    <Router>
      <div className="App">
        <Header/>
        <Body/>
      </div>
    </Router>
  );
}

export default App;

2. 给Home组件添加空值兼容

使用可选链和兜底值避免空值报错:

import React from 'react';
import { useSelector, RootStateOrAny } from 'react-redux';

export default function Home() {
  const auth = useSelector((state: RootStateOrAny) => state.auth);
  // 可选链+兜底值兼容空数据场景
  const username = auth.user?.[0]?.username || '';

  return(
    <div>
      {username ? `Welcome ${username} !` : '用户信息加载中...'}
    </div>
  )
};

3. 优化Body组件的路由判断(可选,避免闪屏)

添加加载状态,避免校验登录态时出现页面闪跳:

export default function Body() {
  const auth = useSelector((state: RootStateOrAny) => state.auth);
  const token = useSelector((state: RootStateOrAny) => state.token);
  const {isLogged} = auth;

  // 登录态校验中显示加载提示
  if (token && !isLogged) {
    return <div>登录状态校验中...</div>
  }
  
  return (
    <Switch>
      <Route path="/signup">
        {isLogged ? <Notfound/> : <Signup/>}
      </Route>
      <Route path="/login">
        {isLogged ? <Notfound/> : <Login/>}
      </Route>
      <Route path="/home">
        {isLogged ? <Home/> : <Login/>}
      </Route>
      <Redirect to="/home"/>
    </Switch>
  )
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 22:45:03