我浏览了React的官方网站,以了解新的生命周期方法getSnapshotBeforeUpdate
但是我不明白这种方法的优势以及确切的使用时间。
下面是docs中的示例,它区分了两种方法。
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) {
const list = this.listRef.current;
return list.scrollHeight - list.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) {
const list = this.listRef.current;
list.scrollTop = list.scrollHeight - snapshot;
}
}
答案 0 :(得分:6)
主要区别在于getSnapshotBeforeUpdate
在更新之前运行,componentDidUpdate
在更新之后运行。
因此,如果您需要保存任何内容以将其覆盖,这就是getSnapshotBeforeUpdate
的目的。这些通常是外部管理的东西(在React术语中为不受控制的),例如您示例中的scrollPosition,或者在与React之外的其他库互操作时(例如jQuery插件)。
主要准则是,如果不确定,您可能不需要。如果这样做,您就会知道。
答案 1 :(得分:5)
您引用的示例上方的两段说明了这一点的必要性:
在上面的示例中,componentWillUpdate用于读取DOM 属性。但是,使用异步渲染时,之间可能会有延迟 “渲染”阶段生命周期(例如componentWillUpdate和render),以及 “提交”阶段生命周期(例如componentDidUpdate)。如果用户这样做 像在此期间调整窗口大小一样,scrollHeight 从componentWillUpdate读取的值将过时。
解决此问题的方法是使用新的“提交”阶段 生命周期,getSnapshotBeforeUpdate。该方法被调用 即将发生突变之前(例如,在 更新)。它可以为React返回一个值作为参数传递给 componentDidUpdate,在发生突变后立即被调用。
换句话说:React 16.6引入了一个名为"Suspense"的新功能。此功能启用异步渲染-反应组件子树的渲染可以延迟(例如,等待网络资源加载)。它也由React内部在favor important DOM updates over others中使用,以提高感知的渲染性能。可能会-导致反应侧虚拟DOM渲染(触发componentWillUpdate
和render()
,但可能包含一些必须等待的异步组件子树)之间的实质性延迟。反射到DOM(触发componentDidUpdate
)。在Suspense之前的较早版本中,由于渲染是完全同步的,因此调用这些生命周期挂钩的时间总是很短,这证明了在componentWillUpdate
中收集DOM信息并在componentDidUpdate
中使用它的模式是合理的,更长的时间。
答案 2 :(得分:1)
我做了一个非常简单的项目,供您了解何时应使用getSnapshotBeforeUpdate生命周期方法,并使用getSnapshotBeforeUpdate存储用户滚动位置并将其用于componentDidUpdate
答案 3 :(得分:1)
嗯,实际上 getSnapshotBeforeUpdate() 在更新之后运行。
想想这有点解释了一切:
class Demo extends React.Component {
constructor(props) {
super(props);
this.state = {x:1};
console.log(1);
}
componentDidMount() {
this.setState({x:2});
console.log(3);
}
shouldComponentUpdate() {
console.log(4);
return true;
}
getSnapshotBeforeUpdate(prevProps, prevState){
console.log(5,prevState.x,this.state.x);
return 999;
}
componentDidUpdate(prevProps, prevState, snapshot) {
console.log(6,snapshot);
}
componentWillUnmount() {
console.log(7);
}
render() {
console.log(2);
return null;
}
}
ReactDOM.render(
<Demo />,
document.querySelector('div')
);
ReactDOM.unmountComponentAtNode(document.querySelector('div'));
输出为:
1
2
3
4
2
5 1 2
6 999
7