什么是React中的getSnapshotBeforeUpdate()?

时间:2018-11-07 16:32:29

标签: javascript reactjs react-native

我浏览了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;
    }
  }

4 个答案:

答案 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渲染(触发componentWillUpdaterender(),但可能包含一些必须等待的异步组件子树)之间的实质性延迟。反射到DOM(触发componentDidUpdate)。在Suspense之前的较早版本中,由于渲染是完全同步的,因此调用这些生命周期挂钩的时间总是很短,这证明了在componentWillUpdate中收集DOM信息并在componentDidUpdate中使用它的模式是合理的,更长的时间。

答案 2 :(得分:1)

我做了一个非常简单的项目,供您了解何时应使用getSnapshotBeforeUpdate生命周期方法,并使用getSnapshotBeforeUpdate存储用户滚动位置并将其用于componentDidUpdate

github仓库 https://github.com/mahdimehrabi/getSnapShot-sample

演示 https://mahdimehrabi.github.io/js/snapshot/

答案 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