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

React中useHistory调用push触发已卸载组件状态更新警告如何解决

问题根因

你触发警告的核心原因是:执行history.push完成路由跳转后,当前Signin组件会被直接卸载,但你在跳转之后还执行了setFormData操作修改组件状态,对已卸载的组件更新状态就会触发该内存泄漏警告。问题主要出现在登录请求成功的回调逻辑中。

修复方案

方案1:调整逻辑执行顺序(最简单,适合你的场景)

把状态更新操作放到路由跳转之前,跳转后不再执行任何组件状态修改即可:

signin(data) //! return response
  .then(response => {
    setAuthentication(response.data.token, response.data.user);
    // 先更新状态,再执行跳转
    setFormData({
        ...formData,
        loading: false,
    });
    // 最后跳转,跳转后无其他操作
    if (isAuthenticated() && isAuthenticated().role === 1) {
        history.push('/admin/dashboard');
    } else {
        history.push('/user/dashboard');
    }
  })

请求失败的catch逻辑不需要修改,因为失败时不会触发跳转,组件仍处于挂载状态,更新状态是合法的。

方案2:通用挂载标记方案(适合多异步逻辑的复杂场景)

如果你的业务有更多异步逻辑不好调整执行顺序,可以用ref标记组件挂载状态,所有状态更新前先判断组件是否仍处于挂载状态:

const Signin = () => {
    let history = useHistory();
    // 新增挂载状态标记
    const isMounted = useRef(true);

    // 组件卸载时更新标记
    useEffect(() => {
        return () => {
            isMounted.current = false;
        }
    }, []);

    // 其余代码不变,修改handleSubmit中的回调逻辑,所有setFormData前加判断
    const handleSubmit = (e) => {
        // 原有验证逻辑不变
        signin(data)
            .then(response => {
                setAuthentication(response.data.token, response.data.user);
                // 仅组件挂载时更新状态
                if (isMounted.current) {
                    setFormData({
                        ...formData,
                        loading: false,
                    });
                }
                if (isAuthenticated() && isAuthenticated().role === 1) {
                    history.push('/admin/dashboard');
                } else {
                    history.push('/user/dashboard');
                }
            })
            .catch(error => {
                // 仅组件挂载时更新状态
                if (isMounted.current) {
                    setFormData({
                        ...formData,
                        loading: false,
                        errorMsg: error.response.data.errorMessage
                    });
                }
            });
    }
    // 其余代码不变
}

额外优化点

你当前用于校验登录状态的useEffect依赖为history,如果你的isAuthenticated方法是从本地存储读取身份信息,没有依赖组件状态,可以将依赖改为空数组,避免不必要的重复执行:

useEffect(() => {
    const userInfo = isAuthenticated();
    if (userInfo?.role === 1) {
        history.push('/admin/dashboard');
    } else if (userInfo?.role === 0) {
        history.push('/user/dashboard');
    }
}, []);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 12:06:07