React控制台日志重复输出问题:useEffect与componentDidMount执行两次
React组件生命周期钩子重复执行的原因
问题描述
开发通知框架时发现jQuery添加的HTML元素数量是预期的两倍,新建React项目复现该问题:
- 函数组件的
useEffect(空依赖数组)控制台输出两次 - 类组件的
componentDidMount生命周期函数控制台输出两次
复现代码
DupeMountTest.js(函数组件)
import React, { useEffect } from "react"; const DupeMountTest = () => { useEffect(() => { console.log("useEffect") }, []) return ( <div> <p>Test</p> </div> ) } export default DupeMountTest
App.js
import { BrowserRouter as Router, Route, Routes, } from "react-router-dom"; import DupeMountTest from "./DupeMountTest"; function App() { return ( <Router> <div className="App"> <Routes> <Route path={"/"} exact element={<DupeMountTest/>}/> </Routes> </div> </Router> ); } export default App
index.js
import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css'; import App from './App'; const root = ReactDOM.createRoot(document.getElementById('root')); root.render( <React.StrictMode> <App /> </React.StrictMode> );
DupeMountTest.js(类组件)
import React, { Component } from "react"; class DupeMountTest extends Component { componentDidMount() { console.log("Mounted") } render() { return ( <div> <p>Test</p> </div> ) } } export default DupeMountTest
问题原因
这是React.StrictMode在开发环境下的刻意行为:
- StrictMode仅在开发模式生效,生产环境不会触发该行为
- 为了帮开发者检测组件中存在的副作用问题,React会刻意重复调用以下方法:
- 类组件的
componentDidMount、componentDidUpdate - 函数组件中依赖数组为空的
useEffect - 还有
useState的初始化函数、useMemo回调等其他方法
- 类组件的
这种重复执行是为了暴露那些仅执行一次才正确、重复执行会出问题的副作用代码(比如你遇到的jQuery重复添加元素),帮助开发者提前修复潜在问题。
内容的提问来源于stack exchange,提问作者BedfordDriggs
相关产品推荐
相关产品推荐

