App组件中ComponentDidMount被调用两次的问题求助
顶层App组件的componentDidMount被调用两次的问题解决
我的顶层App组件的componentDidMount生命周期钩子被调用了两次,已经精简代码排查,排除了缺少key导致重渲染的常见原因,但问题依然存在。
相关代码
index.tsx
import React from 'react'; import ReactDOM from 'react-dom/client'; import './index.css'; import 'bootstrap/dist/css/bootstrap.min.css'; import App from './App'; import reportWebVitals from './reportWebVitals'; const root = ReactDOM.createRoot( document.getElementById('root') as HTMLElement ); root.render( <React.StrictMode> <App global={{baseUrl: "http://localhost", port: 54887}} /> </React.StrictMode> ); // If you want to start measuring performance in your app, pass a function // to log results (for example: reportWebVitals(console.log)) reportWebVitals();
App.tsx
import React from 'react' import CurrentItems, { CurrentItemsProps } from './CurrentItems'; import Navigation, { NavigationProps } from './Navigation'; import { CombinedNavigationProps } from './Navigation'; import './App.css'; import { GlobalProps } from './GlobalProps'; interface AppProps extends GlobalProps {} interface AppState { navigation: NavigationProps; } class App extends React.Component<AppProps, AppState> { constructor(props: AppProps){ super(props); //this.onSelectedViewChange = this.onSelectedViewChange.bind(this); } componentDidMount(){ console.log("app did mount"); } onSelectedViewChange(view: string) { } render(){ if(this.state === undefined || this.state === null){ return (<div>Loading...</div>); } else { return ( <div> Loaded. </div> ); } } } export default App;
控制台输出

问题原因与解决
这是React 18严格模式的预期行为。在React 18的<React.StrictMode>下,为了帮助开发者检测组件中存在的副作用问题,React会故意重复调用以下方法:
- 类组件的
constructor、componentDidMount、componentWillUnmount - 函数组件的
useState、useMemo、useEffect等钩子的初始化函数
解决方式
- 临时规避:如果只是想消除两次调用的现象,可以移除
index.tsx中的<React.StrictMode>包裹,修改后的root.render代码如下:
root.render( <App global={{baseUrl: "http://localhost", port: 54887}} /> );
- 推荐做法:保留严格模式,检查
componentDidMount中的逻辑是否能承受重复执行(比如避免重复发起网络请求、重复订阅事件等)。可以通过添加状态标记来防止重复执行,例如在类组件中增加一个isMounted状态:
componentDidMount(){ if (!this.state?.isMounted) { console.log("app did mount"); this.setState({ isMounted: true }); // 在这里执行你的初始化逻辑 } }
内容的提问来源于stack exchange,提问作者Raeglyn
相关产品推荐
相关产品推荐

