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

React 18 StrictMode下useEffect状态异常问题咨询

React 18 StrictMode 重复渲染/Effect 调用的行为解析与解决方案

这是React 18 StrictMode的预期行为,并非Bug。StrictMode仅在开发环境生效,通过模拟"挂载→卸载→重新挂载"的流程,检测可能导致内存泄漏的不规范副作用。

现象原因拆解

  1. useId的特性:
    StrictMode下第一次渲染生成的ID会被直接丢弃,第二次渲染生成的ID会被保留并用于后续真实渲染。这是因为useId的设计目标是生成组件生命周期内稳定的唯一ID,重复渲染模拟了组件卸载再挂载的场景,确保最终使用的ID符合稳定要求。

  2. useRef的初始化逻辑:
    每次渲染(包括StrictMode的两次渲染)都会重新执行useRef的初始化,将ref.current设为初始值9。第一次渲染时你修改了ref.current为随机数A,但模拟卸载后,第二次渲染组件重新初始化,ref.current再次被设为9,随后修改为随机数B。

  3. Effect的捕获与执行逻辑:
    StrictMode下,React会先执行第一次渲染的Effect,随即调用其清理函数(模拟卸载),然后执行第二次渲染的Effect。你日志中未出现第一次渲染的Effect日志,是因为React在开发环境的双重渲染机制中,会丢弃第一次渲染的状态关联,最终仅保留第二次渲染的Effect执行结果。

解决方案

要适配StrictMode的行为,核心是确保副作用的幂等性,并保证清理函数能正确撤销副作用:

  1. 禁止在渲染阶段修改ref或执行副作用:
    渲染阶段必须是纯函数,所有副作用(如修改ref、DOM操作、数据请求等)都应放在useEffect或useLayoutEffect中:

    const ref = useRef(9);
    const id = useId();
    
    console.log('@@ initial id', id);
    console.log('@@ initial ref', ref.current);
    
    useEffect(() => {
      // 将修改ref的逻辑移至Effect内
      ref.current = Math.random();
      console.log('@@ random ref', ref.current);
    
      console.log('@@ effect id', id);
      console.log('@@ effect ref', ref.current);
    
      return () => {
        // 清理时恢复初始值或执行对应撤销逻辑
        ref.current = 9;
        console.log('@@ unmount id', id);
        console.log('@@ unmount ref', ref.current);
      };
    }, []); // 空依赖确保仅挂载时执行一次
    
  2. 确保清理函数能完全撤销副作用:
    若副作用涉及订阅、定时器、事件监听等,必须在清理函数中完整撤销,避免两次渲染导致的资源泄漏:

    useEffect(() => {
      const subscription = someAPI.subscribe(data => { /* 处理逻辑 */ });
      const timer = setInterval(() => { /* 定时逻辑 */ }, 1000);
    
      return () => {
        subscription.unsubscribe();
        clearInterval(timer);
      };
    }, []);
    
  3. 正确设置Effect依赖项:
    确保useEffect的依赖项完整覆盖所有用到的状态和props,让React能正确跟踪变化,避免不必要的重复执行,同时保证Effect能捕获当前渲染周期的正确状态。

  4. 接受开发环境的双重渲染行为:
    StrictMode仅在开发环境生效,生产环境不会触发两次渲染,因此无需为生产环境修改核心逻辑,只需保证开发环境下的双重渲染不会引发异常即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 02:55:20