各个组件在React生命周期顺序上的保证是什么,并且在任何地方都清楚地记录了它们?
例如,假设我有:
<div>{ x ? <A /> : <B /> }</div>
在这里,在正确与错误之间切换的x
将卸载一个组件,然后安装另一个组件。
是否有[[保证涉及安装的生命周期事件将在这些元素上触发的顺序?
例如,当well documented更改为true时,A的render
将在A的componentDidMount
之前触发是x
。但是,是否保证A的render
和componentDidMount
总是在B的componentWillUnmount
之后触发?进一步说明:如果A和B在这棵树的下方,并且开关位于顶部,它是否会改变?
欢迎任何人回答,但是对此的坚定文件非常感谢。
componentDidUnmount
永远不会在条件渲染中调用。我在codepen上进行了测试,并得到如下结果:
父组件
constructor(props) {
super(props);
this.state = {
flag: false,
}
}
render() {
const { flag } = this.state;
return (
<div>
<h2 onClick={() => this.setState({flag: !flag})}>CONVERT</h2>
<div>
{ flag ? <A /> : <B /> }
</div>
</div>
);
}
子组件A
class A extends React.Component {
componentDidMount() {
console.log('A is mounted');
}
componentWillMount() {
console.log('A will be mounted');
}
componentWillUnmount() {
console.log('A will be unmounted');
}
componentDidUnmount() {
console.log('A is unmounted');
}
render() {
return (
<h1>A</h1>
);
}
}
子组件B
Almost the same as A :D
我点击了结果
CONVERT
两次,结果是:"B will be mounted" // first render
"B is mounted"
"B will be unmounted" // first click
"A will be mounted"
"A is mounted"
"A will be unmounted" // second click
"B will be mounted"
"B is mounted"
componentDidUnmount
从未在条件渲染中被调用。
Github -- React-Mounting-Tests
it('prepares new child before unmounting old', () => {
const log = [];
class Spy extends React.Component {
UNSAFE_componentWillMount() {
log.push(this.props.name + ' componentWillMount');
}
render() {
log.push(this.props.name + ' render');
return <div />;
}
componentDidMount() {
log.push(this.props.name + ' componentDidMount');
}
componentWillUnmount() {
log.push(this.props.name + ' componentWillUnmount');
}
}
class Wrapper extends React.Component {
render() {
return <Spy key={this.props.name} name={this.props.name} />;
}
}
const container = document.createElement('div');
ReactDOM.render(<Wrapper name="A" />, container);
ReactDOM.render(<Wrapper name="B" />, container);
expect(log).toEqual([
'A componentWillMount',
'A render',
'A componentDidMount',
'B componentWillMount',
'B render',
'A componentWillUnmount',
'B componentDidMount',
]);
});
此实现背后的原因可以找到 @ commit message for test
“这与我们在Fiber中所做的相匹配-并且这样做是唯一的在卸载旧版本之前我们可以在后台准备新视图的方式的。“保证此订单!
componentWillMount()直到在线学习小组会议上才意识到的一个重大障碍是componentWillMount()在2018年已弃用。虽然可以继续使用它(直到React 17.0),但这不是最佳实践,因为它不安全异步渲染。如果确实选择继续使用它,则应使用UNSAFE_componentWillMount()。
原因在componentWillMount()中使用fetch调用会导致组件首先使用空数据进行渲染,因为componentWillMount()不会在首次渲染该组件之前返回。
由于JavaScript事件是异步的,因此当您进行API调用时,浏览器在调用仍在进行中时会继续执行其他工作。使用React,在渲染组件时,它不会等待componentWillMount()完成,因此该组件会继续渲染。
话虽这么说,您将需要创建一个看起来仍然可以显示但没有希望显示的数据的组件。在数据存在之前,没有办法(甚至没有计时器)停止呈现组件。
[在构建项目时,我不知道componentWillMount()的弃用,而且我不明白为什么总是收到“无法读取未定义的属性'map'的错误”错误。我很困惑,因为我有一个数组,应该在数组中填充数据,但实际上不是。
事实证明,这是完全而全面的,因为组件最初是用空数据呈现的,所以数组是空的,因此无法进行迭代。只是在这一点上,我才知道使用componentDidMount()是最佳实践。
componentDidMount()调用获取数据的最佳位置是componentDidMount()。与componentWillMount()两次调用,一次服务器调用和一次客户端调用相比,componentDidMount()在客户端仅被调用一次。当客户端从服务器接收数据并且在浏览器中显示数据之前,在初始渲染之后调用该方法。由于数据要等到初始渲染后才能加载,因此开发人员需要正确设置组件的初始状态。
附带说明,通过componentDidMount(),您可以使用计时器并经常更新数据,而无需用户刷新页面。我想说这是一个非常整洁的功能,可以在项目/网站中使用。