React 开启 Strict Mode 后 useEffect 为啥执行了两次?
我在开发 React 应用时,发现只要在根组件包了 StrictMode,里面的 useEffect 就会执行两次,明明只写了一次逻辑。这是 bug 吗?还是我哪里理解错了?
比如下面这段代码,在控制台会打印两次 “mounted”:
import { useEffect } from 'react';
function MyComponent() {
useEffect(() => {
console.log('mounted');
}, []);
return <div>Hello</div>;
}
我试过移除 StrictMode 包裹,就只打印一次了。但官方文档说 Strict Mode 不会影响生产环境,那开发时这样会不会影响调试逻辑?比如初始化请求发了两次?
React 在开发环境下,会故意把 useEffect 的副作用函数执行两次(仅限于开发模式,生产环境完全正常),前提是组件挂载时触发的 effect。这样设计是因为很多开发者会把副作用写成“只执行一次”,但实际逻辑里可能没处理好清理逻辑,比如订阅、定时器、网络请求这些,如果组件挂载又卸载再挂载,可能就会重复触发副作用。
StrictMode 假装组件被挂载→卸载→再挂载一遍,帮你提前暴露这类问题。比如你发了两次请求,其实就说明你没在 cleanup 里取消请求,或者没做幂等处理——这在真实场景下(比如网络抖动、用户快速切换 tab)是可能发生的。
建议改成这样来避免开发时的副作用重复执行(尤其是副作用有明显外部影响时):
关键是 cleanup 里要清理掉所有可能残留的副作用。如果你只是打印日志看执行次数,完全不用管;但要是发请求、写本地存储、注册事件监听这些,就一定要在 cleanup 里处理干净。
最后提醒一句:StrictMode 的双执行只发生在开发环境,生产环境打包后(
npm run build或yarn build)就完全正常了,不会多执行一次。所以别怕,大胆用 StrictMode,它是在帮你抓隐藏 bug,不是添乱。