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

React中useEffect清理函数为何在渲染时触发?

解决React 18 Strict Mode下useEffect清理函数误触发导致状态无法更新的问题

你的问题根源是React 18开发环境的Strict Mode特性:它会刻意重复执行组件的挂载→卸载→挂载流程,用来检测潜在的组件bug。这就导致你的useSignin钩子中,空依赖的useEffect清理函数被提前触发,把unmounted状态设为true,但组件实际仍处于挂载状态,后续异步登录操作完成后,因unmounted为true无法更新loading和error状态。

解决方案:用Ref替代State跟踪组件挂载状态

useState的更新会触发重渲染,且受闭包影响,不适合用来跟踪组件挂载状态。改用useRef可以避免这些问题,因为Ref的current属性是可变的,不会触发重渲染,且在组件生命周期内保持引用一致性。

修改后的useSignin钩子代码:

import { useEffect, useState, useRef } from "react";
import { useAuth } from "./useAuth";
import { auth } from "../firebase/config";

export default function useSignin() {
    // 用Ref跟踪组件是否挂载
    const isMountedRef = useRef(true);
    const [error, setError] = useState(null);
    const [loading, setLoading] = useState(false);
    const { dispatch } = useAuth();

    const signIn = async (email, password) => {
        setLoading(true);
        setError(null);

        try {
            const res = await auth.signInWithEmailAndPassword(email, password);
            dispatch({
                type: "LOGIN",
                payload: res.user,
            });

            // 只有组件挂载时才更新状态
            if (isMountedRef.current) {
                setLoading(false);
                setError(null);
            }
        } catch (err) {
            if (isMountedRef.current) {
                setError(err.message);
                setLoading(false);
            }
        }
    };

    useEffect(() => {
        // 组件卸载时标记为未挂载
        return () => {
            isMountedRef.current = false;
        };
    }, []);

    return { signIn, error, loading };
}

为什么这个方案有效?

  1. useRef的current属性不会触发组件重渲染,避免了Strict Mode下的状态重置问题。
  2. 它不受闭包限制,异步操作完成时能准确读取当前组件的挂载状态。
  3. 严格遵循了React的最佳实践,既保留了防止卸载后更新状态的逻辑,又适配了Strict Mode的特性。

临时方案(不推荐):关闭Strict Mode

如果你只是临时测试,可以移除项目入口文件(通常是index.js)中的<StrictMode>标签,但不建议长期这么做——Strict Mode能帮你提前发现很多潜在的组件问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 20:30:43