Skip to content
 

React 严格模式下组件渲染两次的原因及解决方案

更新: 9/4/2025字数: 0 字 时长: 0 分钟

一、为什么严格模式会导致组件渲染两次?

React 的严格模式(Strict Mode)下,组件会故意渲染两次,这是 React 团队特意设计的行为,目的是帮助开发者发现潜在的问题。

主要原因

  1. 检测副作用问题React 通过故意重复调用以下方法来识别不纯的代码:

    • 组件函数体
    • render 方法
    • setState 更新函数
    • useStateuseMemouseReducer 的初始化函数
  2. 准备并发模式:帮助开发者提前发现可能在并发渲染中出现的问题

  3. 识别不安全的生命周期:帮助发现将被废弃的生命周期方法的使用

二、哪些情况会触发双渲染?

严格模式下的双渲染行为主要发生在开发环境中,生产环境不会出现这种情况。

具体触发场景

  1. 组件挂载阶段

    jsx
    function MyComponent() {
      console.log("渲染"); // 开发环境下会打印两次
      return <div>Hello</div>;
    }
  2. 状态更新时

    jsx
    const [count, setCount] = useState(0);
    // setCount() 调用时相关逻辑也会执行两次
  3. Effect 清理和设置

    jsx
    useEffect(() => {
      console.log("Effect运行"); // 开发环境下会打印两次
      return () => console.log("清理"); // 也会立即执行清理
    }, []);

三、为什么这是有价值的?

虽然双渲染看起来像是个"bug",但它实际上帮助开发者发现了很多潜在问题:

  1. 识别不纯的计算

    jsx
    let globalIndex = 0;
    
    function UnpureComponent() {
      globalIndex++; // 严格模式下会发现这个副作用问题
      return <div>{globalIndex}</div>;
    }
  2. 发现 Effect 问题

    jsx
    useEffect(() => {
      socket.connect();
      // 严格模式下会立即调用清理函数,暴露忘记清理的问题
    }, []);
  3. 准备并发特性:帮助组件适应未来可能中断和恢复的渲染过程

四、如何应对双渲染?

1. 编写纯组件

确保组件渲染没有副作用:

jsx
// ✅ 纯函数组件
function PureComponent({ data }) {
  const computedValue = useMemo(() => expensiveCalculation(data), [data]);
  return <div>{computedValue}</div>;
}

2. 正确处理 Effects

使用清理函数保持幂等性:

jsx
useEffect(() => {
  const timer = setInterval(() => {}, 1000);
  return () => clearInterval(timer); // 正确清理
}, []);

3. 使用 useMemo/useCallback 优化

避免不必要的昂贵计算:

jsx
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);

4. 生产环境验证

记住双渲染只发生在开发环境,生产环境不会出现:

jsx
if (process.env.NODE_ENV === "production") {
  // 生产环境特定逻辑
}

五、什么时候应该禁用严格模式?

大多数情况下不应该禁用严格模式,但在某些特殊场景可以考虑:

  1. 性能敏感的演示/基准测试
  2. 与某些不兼容严格模式的第三方库一起使用时

禁用方法(不推荐):

jsx
// 移除或注释掉 StrictMode
ReactDOM.render(
  // <React.StrictMode>
    <App />
  // </React.StrictMode>,
  document.getElementById('root')
);

我见青山多妩媚,料青山见我应如是。