美文网首页工作生活
ReactV16.3+新增的api

ReactV16.3+新增的api

作者: 泉泉泉泉泉泉 | 来源:发表于2019-07-06 19:39 被阅读0次
    • React16新的生命周期弃用了componentWillMount、componentWillReceivePorps,componentWillUpdate
    • 新增了getDerivedStateFromProps、getSnapshotBeforeUpdate来代替弃用的三个钩子函数(componentWillMount、componentWillReceivePorps,componentWillUpdate)
    • React16并没有删除这三个钩子函数,但是不能和新增的钩子函数(getDerivedStateFromProps、getSnapshotBeforeUpdate)混用,React17将会删除componentWillMount、componentWillReceivePorps,componentWillUpdate
    • 新增了对错误的处理(componentDidCatch)

    getDerivedStateFromProps

    新的静态getDerivedStateFromProps生命周期在组件实例化以及接收新props后调用。它可以返回一个对象来更新state,或者返回null来表示新的props不需要任何state更新。
    与componentDidUpdate一起,这个新的生命周期将覆盖旧版componentWillUpdate的所有用例。

    getSnapshotBeforeUpdate

    新的getSnapshotBeforeUpdate生命周期在更新之前被调用(例如,在DOM被更新之前)。此生命周期的返回值将作为第三个参数传递给componentDidUpdate。 (这个生命周期不是经常需要的,但可以用于在恢复期间手动保存滚动位置的情况。)
    与componentDidUpdate一起,这个新的生命周期应该覆盖传统componentWillReceiveProps的所有用例。

    React15部分生命周期函数的副作用

    1.props改变的副作用

    与componentWillUpdate一样,componentWillReceiveProps可能会多次调用但是只更新一次。出于这个原因,避免在此方法中导致的副作用非常重要。相反,应该使用componentDidUpdate,因为它保证每次更新只调用一次。

    2.在更新之前读取DOM属性

    下面是一个组件的例子,它在更新之前从DOM中读取属性,以便在列表中保持滚动位置。

    class ScrollingList extends React.Component {
      listRef = null;
      previousScrollOffset = null;
    
      componentWillUpdate(nextProps, nextState) {
        // Are we adding new items to the list?
        // Capture the scroll position so we can adjust scroll later.
        if (this.props.list.length < nextProps.list.length) {
          this.previousScrollOffset =
            this.listRef.scrollHeight - this.listRef.scrollTop;
        }
      }
    
      componentDidUpdate(prevProps, prevState) {
        // If previousScrollOffset is set, we've just added new items.
        // Adjust scroll so these new items don't push the old ones out of view.
        if (this.previousScrollOffset !== null) {
          this.listRef.scrollTop =
            this.listRef.scrollHeight -
            this.previousScrollOffset;
          this.previousScrollOffset = null;
        }
      }
    
      render() {
        return (
          `<div>`
            {/* ...contents... */}
          `</div>`
        );
      }
      setListRef = ref => {
        this.listRef = ref;
      };
    }
    

    在上面的例子中,componentWillUpdate被用来读取DOM属性。但是,对于异步渲染,“render”阶段生命周期(如componentWillUpdate和render)与“commit”阶段生命周期(如componentDidUpdate)之间可能存在延迟。如果用户在这段时间内做了类似调整窗口大小的操作,则从componentWillUpdate中读取的scrollHeight值将失效。

    解决此问题的方法是使用新的“commit”阶段生命周期getSnapshotBeforeUpdate。在数据发生变化之前立即调用该方法(例如,在更新DOM之前)。它可以将React的值作为参数传递给componentDidUpdate,在数据发生变化后立即调用它。

    这两个生命周期可以像这样一起使用:

    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>`
            {/* ...contents... */}
          `</div>`
        );
      }
    
      setListRef = ref => {
        this.listRef = ref;
      };
    }
    

    PS:如果您正在编写共享组件,那么react-lifecycles-compat polyfill可以使新的getSnapshotBeforeUpdate生命周期与旧版本的React一起使用。详细了解如何使用它

    开源项目维护者

    当React 16.3发布时,我们还将发布一个新的npm包, react-lifecycles-compat。该npm包会填充组件,以便新的getDerivedStateFromPropsgetSnapshotBeforeUpdate生命周期也可以与旧版本的React(0.14.9+)一起使用。
    要使用这个polyfill,首先将它作为依赖项添加到您的库中:

    # Yarn
    yarn add react-lifecycles-compat
    
    # NPM
    npm install react-lifecycles-compat --save
    

    使用polyfill将组件向后兼容旧版本的React:

    import React from 'react';
    import {polyfill} from 'react-lifecycles-compat';
    
    class ExampleComponent extends React.Component {
      static getDerivedStateFromProps(nextProps, prevState) {
        // Your state update logic here ...
      }
    }
    
    // Polyfill your component to work with older versions of React:
    polyfill(ExampleComponent);
    
    export default ExampleComponent;
    

    参考博客:
    https://segmentfault.com/a/1190000014456811?utm_source=channel-hottest
    https://segmentfault.com/a/1190000016617400
    https://www.cnblogs.com/tianshu/p/9313945.html
    https://blog.csdn.net/wust_cyl/article/details/84306393

    相关文章

      网友评论

        本文标题:ReactV16.3+新增的api

        本文链接:https://www.haomeiwen.com/subject/obwocctx.html