最近在整理生命周期相关的知识内容,然后发现一个奇怪的现象,即组件的生命周期会运行2次!经过确认不是代码问题,于是开始找度娘,终于找到其原因-React中的严格模式,在这里记录一下
一、问题重现
如图所示,当组件初始化渲染时,每个周期都走了2次,按理说初始化时所有运行的生命周期都仅执行一次。
代码
import { Component } from "react";
class Com extends Component {
constructor(props) {
super(props);
this.state = {
value: 0,
};
console.log(this.props);
}
componentWillMount() {
console.log("组件即将挂载到页面上 - componentWillMount");
}
render() {
console.log("组件渲染虚拟dom - render")
return (
<div> </div>
);
}
componentDidMount(){
console.log('虚拟dom此时已经变成真实dom,挂载到页面上了 - componentDidMount')
}
}
export default Com;
现象
二、问题原因
之所以会调用2次,其实都是因为React中的严格模式 - StrictMode
StrictMode
是一个用来检查项目中潜在问题的工具。与 Fragment
一样,StrictMode
不会渲染任何可见的 UI。它为其后代元素触发额外的检查和警告。
需要注意的是:严格模式检查仅在开发模式下运行;它们不会影响生产构建。
StrictMode
的作用有很多,如下所示:
1、识别不安全的生命周期;
2、关于使用过时字符串 ref
API 的警告;
3、关于使用废弃的 findDOMNode
方法的警告;
4、检测意外的副作用;
5、检测过时的 context API
。
但此篇文章就不展开一一赘述了,这里仅回归到本文探讨的问题:组件的一次更新流程,在视图真正刷新之前的部分都是可能被多次调用的,因而这些部分中不能出现副作用,开发环境下会刻意触发两次以使得开发者能注意到误用的副作用。
三、问题解决
知道了原因之后,问题就很好解决了,我们只需要将StrictMode
注释掉即可,如下所示。(一般是在index.js文件中使用)
import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
import { BrowserRouter } from "react-router-dom";
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<BrowserRouter>
{/* <React.StrictMode> */}
<App />
{/* </React.StrictMode> */}
</BrowserRouter>
);
reportWebVitals();
此时运行项目,组件的生命周期触发现象如下,确实已经正常了!