Next.js 新搭建的项目,在使用 useEffect 时,会触发两次,经过排查,发现问题不是出现在 Next.js 上,而是出现在 React 上。React18 版本之后,在严格模式开发环境下,useEffect 会默认触发两次。

为什么在 StictMode 下,useEffect 要故意触发两次?

React 18 在严格模式下(StrictMode)下,useEffect 被故意触发两次是为了模拟立即卸载组件和重新挂载组件的情况。这是为了帮助开发者提前发现重复挂载造成的 Bug 的代码,在生产环境就还是保持正常。点击这里查看详细文档

useEffect(() => {
  // 触发两次
}, [])

解决方法

在 Next.js 的配置文件 nextjs.config.js 中,添加如下配置:

module.exports = {
  reactStrictMode: false,
}

如果是 Create React App 创建的项目,可以通过关闭严格模式来解决,移除 <StrictMode> 组件即可。

import React, { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import App from './App';
const rootElement = document.getElementById('root');
const root = createRoot(rootElement);
root.render(
  <StrictMode>
    <App />
  </StrictMode>
);

移除后:

import React from 'react';
import { createRoot } from 'react-dom/client';
import App from './App';
const rootElement = document.getElementById('root');
const root = createRoot(rootElement);
root.render(
  <App />
);
非必要不建议移除严格模式,严格模式虽然开发重复触发会影响我们的编码体验,但是可以更好地避免一些未知的问题,适应它才是正确的选择。