在本章节中我们将讨论 React 组件的生命周期。
组件的生命周期可分成三个状态:
Mounting:已插入真实 DOM
Updating:正在被重新渲染
Unmounting:已移出真实 DOM
初始化阶段:
getDefaultProps:获取实例的默认属性
getInitialState:获取每个实例的初始化状态
componentWillMount:组件即将被装载、渲染到页面上
render:组件在这里生成虚拟的 DOM 节点
componentDidMount:组件真正在被装载之后
运行中状态:
componentWillReceiveProps:组件将要接收到属性的时候调用
shouldComponentUpdate:组件接受到新属性或者新状态的时候(可以返回 false,接收数据后不更新,阻止 render 调用,后面的函数不会被继续执行了)
componentWillUpdate:组件即将更新不能修改属性和状态
render:组件重新描绘
componentDidUpdate:组件已经更新
销毁阶段:
componentWillUnmount:组件即将销毁
在未来 v17.0 版本中即将被移除的三个生命周期函数 componentWillMount `,componentWillReceiveProps ,componentWillUpdate (现在这三个钩子函数依然可以使用).
新增两个钩子函数:
1. getDerivedStateFromProps(nextProps, prevState):
组件初始(重新渲染)加载时,获取当前的props与state的值(在此钩子函数中不能使用this),再此比较返回最新值对象(这个返回简单点说就相当于setState),注意添加 条件不满足时 return null;
官方例子:
static getDerivedStateFromProps(nextProps, prevState) {
if (nextProps.translateX !== prevState.translateX) {
return {
translateX: nextProps.translateX,
};
}
return null;
}
2. getSnapshotBeforeUpdate(prevProps, prevState):
getSnapshotBeforeUpdate 会在最终的 render 之前被调用,也就是说在 getSnapshotBeforeUpdate 中读取到的 DOM 元素状态是可以保证与 componentDidUpdate 中一致的。虽然 getSnapshotBeforeUpdate 不是一个静态方法,但我们也应该尽量使用它去返回一个值。这个值会随后被传入到 componentDidUpdate 中,然后我们就可以在 componentDidUpdate 中去更新组件的状态,而不是在 getSnapshotBeforeUpdate 中直接更新组件状态。
官方例子:
class ScrollingList extends React.Component {
listRef = null;
getSnapshotBeforeUpdate(prevProps, prevState) {
// Are we adding new items to the list?
// Capture the scroll position so we can adjust scroll later.
if (prevProps.list.length < this.props.list.length) {
return (
this.listRef.scrollHeight - this.listRef.scrollTop
);
}
return null;
}
componentDidUpdate(prevProps, prevState, snapshot) {
// If we have a snapshot value, we've just added new items.
// Adjust scroll so these new items don't push the old ones out of view.
// (snapshot here is the value returned from getSnapshotBeforeUpdate)
if (snapshot !== null) {
this.listRef.scrollTop =
this.listRef.scrollHeight - snapshot;
}
}
render() {
return (
<div ref={this.setListRef}>
{/* ...contents... */}
</div>
);
}
setListRef = ref => {
this.listRef = ref;
};
}
