React 的 getDerivedStateFromProps 生命周期 究竟有啥用 ?

每个项目产品都要加埋点,加500行埋点是不是会占用你一两天的时间而且很容易犯错,想只用一小时准确加完这500行埋点剩下一天喝茶聊天么?来试试这520工具, 高效加埋点,目前我们公司100号前端都在用,因为很好用,所以很自然普及开来了,推荐给大家吧

http://www.520webtool.com/

自己开发所以免费,埋点越多越能节约时间,点两下埋点就加上了,还不会犯错,里面有使用视频,反正免费 😄

随着react v16.3版本的发布,

最大的变动莫过于生命周期去掉了以下三个

componentWillMount
componentWillReceiveProps
componentWillUpdate
同时为了弥补失去上面三个周期的不足又加了两个

static getDerivedStateFromProps
getSnapshotBeforeUpdate
如下图:
53884612-fa2b0800-4056-11e9-879f-050e0b33e0e9.png?ynotemdtimestamp=1551878671356

新的静态生命周期方法 getDerivedStateFromProps 是根据props来派生出新的state

前段时间在使用 getDerivedStateFromProps 时,只是机械的用它和 componentDidUpdate 来替换 componentWillReceiveProps,已达到通过修改props,来修改state的作用,比如下面这个例子:

// Before
class ExampleComponent extends React.Component {
  state = {
    externalData: null,
  };
 
  componentDidMount() {
    // this.props.id === undefined
    this._loadData(this.props.id);
  }
 
  componentWillReceiveProps(nextProps) {
      //当某个props中的值发生变化时(此处是id属性)
      if (nextProps.id !== this.props.id) {
        //初始化state中的externalData值为null
        this.setState({externalData: null});
        //基于新的id属性,异步获取数据,并在完成时设置externalData的值
        this._loadData(nextProps.id);
    }
  }
 
  render() {
    if (this.state.externalData === null) {
      // Render loading state ...
    } else {
      // Render real UI ...
    }
  }
     
  _loadData(id) {
  
    if (!id) {return;}
  
    loadData(id).then(
      externalData => {
        this.setState({externalData});
      }
    );
  }
}

改写之后:

// After Wrong
class ExampleComponent extends React.Component {
  state = {
    externalData: null,
    prevId: this.props.id
  };
 
  static getDerivedStateFromProps(nextProps, prevState) {
    // Store prevId in state so we can compare when props change.
    // Clear out previously-loaded data (so we don't render stale stuff).
    if (nextProps.id !== prevState.prevId) {
      return {
        externalData: null,
        prevId: nextProps.id,
      };
    }
 
    // No state update necessary
    return null;
  }
 
  componentDidUpdate(prevProps, prevState) {
    if (this.state.externalData === null) {
      this._loadData(this.props.id);
    }
  }
 
  componentDidMount() {
    this._loadData(this.props.id);
  }
 
  render() {
    if (this.state.externalData === null) {
      // Render loading state ...
    } else {
      // Render real UI ...
    }
  }
 
  _loadData(id) {
  
    if (!id) {return;}
  
    loadData(id).then(
      externalData => {
        this.setState({externalData});
      }
    );
  }
}

getDerivedStateFromProps 存在只为了一个目的。它让组件在 props 发生改变时更新它自身的内部 state。 一个常规的准则,应该保守地使用 derived state。

看了一下:https://reactjs.org/blog/2018... 中有提到两个使用 getDerivedStateFromProps 的反模式:

无条件地将 prop 复制给 state
当 props 改变时清除 state,使 props 和 state 中的值,保持一致
这个例子比较符合第二种情况。就是为了比较id是否更新,把props中的id,存到了state 中 prevId。
并且 在 componentDidUpdate 的时候, 根据 state 中的 externalData 是否改变来判断是否需要异步加载新的数据。

这样写也没有错误,但是没有必要这样写,这样写反而增加了程序的复杂程度。

// Right
class ExampleComponent extends React.Component {
  state = {
    externalData: null,
  };
 
  componentDidUpdate(prevProps, prevState) {
    if (this.props.id && this.props.id !== prevProps.id) {
      this._loadData(this.props.id);
    }
  }
 
  componentDidMount() {
    this._loadData(this.props.id);
  }
 
  render() {
    if (this.state.externalData === null) {
      // Render loading state ...
    } else {
      // Render real UI ...
    }
  }
 
  _loadData(id) {
  
    if (!id) {return;}
  
    loadData(id).then(
      externalData => {
        this.setState({externalData});
      }
    );
  }
}

因为上面的例子属于异步的更新,所以直接使用 componentDidUpdate 来确保是基于正确的 props 来更新 state 足以。

对不受控组件,如果你在一个特殊的 prop (通常是 ID)改变时试图重置 state,你有一些选择:

推荐:重置所有内部 state,使用 key 属性
替代方案1:仅重置确定的 state 字段,监听特定属性的变化(例如: props.id)。
替代方案2:你也可以考虑使用 refs 调用一个命令式实例方法。

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值