为什么 React 18 里的类组件在严格模式下会执行的模拟渲染 constructor 会先于首次渲染的 componentDidMount 执行?
react 18 里的类组件在严格模式下会执行一次模拟渲染, 在类组件的生命周期里表现如下first.constructor -> second.constructor -> first.componentDidMount -> first.componentWillUnmount -> second.componentDidMount
一个比较简单的例子就是,复现链接(https://playcode.io/1531037)
组件卸载的时候改的是同一个对象,导致第一次卸载时把第二次在 constructor 里初始化的对象给重置了
import React from 'react';
export class App extends React.Component {
constructor(props) {
super(props);
console.log(0);
}
componentDidMount() {
console.log(1);
}
componentWillUnmount() {
console.log(2);
}
render() {
return <div>1</div>;
}
}
上面的输出是
00121
这个问题会导致在第二次渲染 constructor 执行时里面初始化的内容被第一次渲染卸载时重置,导致第二次渲染时要用到初始化内容时报错,如下(复现 https://playcode.io/1531064)
import React from 'react';
function A() {};
export class App extends React.Component {
ob;
constructor(props) {
super(props);
console.log(0);
this.ob = new A();
}
componentDidMount() {
console.log(1);
console.log(this.ob);
//all operations on ob will report an error
}
componentWillUnmount() {
console.log(2);
this.ob = null;
}
render() {
return <div>1</div>;
}
}
目前的修补方法是把初始化改到 componentDidMount 里面,但是这个问题的原因是什么呢?为什么两次渲染改到了同一个对象?
回复
1个回答
test
2024-06-30
你可以把对象的初始化放在 componentDidMount 里,或者用 React 的新的生命周期方法 getDerivedStateFromProps 或者 getSnapshotBeforeUpdate。这两个方法在每次渲染前都会被调用
回复
适合作为回答的
- 经过验证的有效解决办法
- 自己的经验指引,对解决问题有帮助
- 遵循 Markdown 语法排版,代码语义正确
不该作为回答的
- 询问内容细节或回复楼层
- 与题目无关的内容
- “赞”“顶”“同问”“看手册”“解决了没”等毫无意义的内容