【问题标题】:What is getSnapshotBeforeUpdate() in React?React 中的 getSnapshotBeforeUpdate() 是什么?
【发布时间】:2018-11-07 16:32:29
【问题描述】:

我通过下面的React官网了解了新的生命周期方法getSnapshotBeforeUpdate

但我不明白这种方法的优点以及我们应该在什么时候使用。

以下是文档中的示例,它区分了两种方法。

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;
    }
  }

【问题讨论】:

    标签: javascript reactjs react-native


    【解决方案1】:

    你引用的例子上面的两段解释了这一点:

    在上面的例子中,componentWillUpdate 用于读取 DOM 财产。但是,对于异步渲染,可能会有延迟 “渲染”阶段生命周期(如 componentWillUpdate 和渲染)和 “提交”阶段生命周期(如 componentDidUpdate)。如果用户这样做 在此期间调整窗口大小,scrollHeight 从 componentWillUpdate 读取的值将是陈旧的。

    解决这个问题的方法是使用新的“提交”阶段 生命周期,getSnapshotBeforeUpdate。这个方法被调用 在发生突变之前(例如,在 DOM 之前 更新)。它可以返回一个值让 React 作为参数传递给 componentDidUpdate,在发生突变后立即调用。

    换句话说:React 16.6 引入了一个名为"Suspense" 的新功能。此功能启用异步渲染 - 可以延迟渲染反应组件的子树(例如等待网络资源加载)。它也被 React 内部使用到favor important DOM updates over others 以提高感知的渲染性能。这可能 - 正如人们所期望的那样 - 导致反应端虚拟 DOM 渲染(触发 componentWillUpdaterender(),但可能包含一些必须等待的异步组件子树)和对 DOM 的实际反射之间的大量延迟(触发componentDidUpdate)。在 Suspense 之前的旧 react 版本中,这些生命周期钩子总是在很少延迟的情况下被调用,因为渲染是完全同步的,这证明了在 componentWillUpdate 中收集 DOM 信息并在 componentDidUpdate 中使用它的模式是合理的,但现在情况不再如此。

    【讨论】:

      【解决方案2】:

      主要区别在于getSnapshotBeforeUpdate在更新之前运行,componentDidUpdate在更新之后运行。

      因此,如果您需要在覆盖之前保存任何内容,这就是 getSnapshotBeforeUpdate 的用途。这些通常是外部管理的东西(在 React 术语中是不受控制的),例如您示例中的 scrollPosition,或者与 React 之外的其他库(例如 jQuery 插件)进行互操作时。

      主要准则是,如果您不确定,您可能不需要它。如果你这样做,你会知道的。

      【讨论】:

        【解决方案3】:

        我做了一个非常简单的项目让你了解我们什么时候应该使用 getSnapshotBeforeUpdate 生命周期方法,我使用 getSnapshotBeforeUpdate 来存储用户滚动位置并在 componentDidUpdate 中使用它

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

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

        【讨论】:

          【解决方案4】:

          好吧,实际上 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
          

          【讨论】:

            猜你喜欢
            • 2019-04-10
            • 2020-04-28
            • 2019-04-09
            • 1970-01-01
            • 1970-01-01
            • 2019-06-20
            • 2018-05-18
            相关资源
            最近更新 更多