React16版本新增生命周期getDerivedStateFromProps替代componentWillReceiveProps

一直使用componentWillReceiveProps来进行当props发生变化时更新state,重新渲染。但是使用react16.3及以上版本时,提示componentWillReceiveProps将在17版本时被废弃。可以使用getDerivedStateFromProps来进行替代。于是研究了一下如何用getDerivedStateFromProps替代componentWillReceiveProps。

1 含义

getDerivedStateFromProps生命周期的意思就是从props中获取state,其功能实际上就是将传入的props映射到state上面。

这个函数会在每次re-rendering之前被调用,意味着即使你的props没有任何变化,而是父state发生了变化,导致子组件发生了re-render,这个生命周期函数依然会被调用。

2 使用对比
基本使用

使用componentWillReceiveProps时:

    componentWillReceiveProps(nextProps){
        let t_aTC_param = nextProps.articleList;
        this.setState({ s_aI4_tag_id: t_aTC_param.tag_id, s_str_tag_name: t_aTC_param.tag_name }) //更新state
    }

而getDerivedStateFromProps是一个静态函数,也就是这个函数不能通过this访问到class的属性,也并不推荐直接访问属性。而是应该通过参数提供的nextProps以及prevState来进行判断,根据新传入的props来映射到state。

需要注意的是,如果props传入的内容不需要影响到你的state,那么就需要返回一个null,这个返回值是必须的,所以尽量将其写到函数的末尾。

    static getDerivedStateFromProps(nextProps, prevState) {
        const { tag_id,tag_name } = nextProps.articleList;
        if(tag_id !== prevState.s_aI4_tag_id){ //传入的props与state不同
            return {s_aI4_tag_id:tag_id,s_str_tag_name:tag_name} //将传入的props映射到state上
        }
        return null
    }

componentWillReceiveProps的写法并不存在什么功能上的问题,将componentWillReceiveProps标记为deprecated的原因也并不是因为功能问题,而是性能问题。

当外部多个属性在很短的时间间隔之内多次变化,就会导致componentWillReceiveProps被多次调用。这个调用并不会被合并,如果这次内容都会触发异步请求,那么可能会导致多个异步请求阻塞。

而setState操作是会通过transaction进行合并的,由此导致的更新过程是批量的,而react中大部分的更新过程的触发源都是setState,所以render触发的频率并不会非常频繁

因此在使用getDerivedStateFromProps的时候,遇到了上面说的props在很短的时间内多次变化,也只会触发一次render,也就是只触发一次getDerivedStateFromProps,从而提高了性能。

异步

以前,可以在props发生改变的时候,在componentWillReceiveProps中进行异步操作,将props的改变驱动到state的改变。

    componentWillReceiveProps(nextProps){
        let t_aTC_param = nextProps.articleList;
        this.setState({ s_aI4_tag_id: t_aTC_param.tag_id, s_str_tag_name: t_aTC_param.tag_name }) //更新state
        this.query(t_aTC_param.pageIndex, t_aTC_param.tag_id); //根据新的props内容,进行异步数据查询
    }

那么,如何使用getDerivedStateFromProps进行异步的处理呢?

    static getDerivedStateFromProps(nextProps, prevState) {
        const { tag_id,tag_name } = nextProps.articleList;
        if(tag_id !== prevState.s_aI4_tag_id){
            return {s_aI4_tag_id:tag_id,s_str_tag_name:tag_name}
        }
        return null
    }
    // 在componentDidUpdate中进行异步操作,驱动数据的变化
    componentDidUpdate(prevProps,prevState){  
        if(prevState.s_aI4_tag_id !== this.state.s_aI4_tag_id){ //前一个state与新的state不符,触发异步更新
            //异步刷新数据
            this.query(1, this.state.s_aI4_tag_id); //异步更新数据
        }
    }
3 建议

根据官网建议,getDerivedStateFromProps (以及其他派生 state)是一个高级复杂的功能,应该保守使用。
设计组件时参考以下建议方案:

完全可控的组件

从组件里删除 state

function EmailInput(props) {
  return <input onChange={props.onChange} value={props.email} />;
}
有 key 的非可控组件
class EmailInput extends Component {
  state = { email: this.props.defaultEmail };

  handleChange = event => {
    this.setState({ email: event.target.value });
  };

  render() {
    return <input onChange={this.handleChange} value={this.state.email} />;
  }
}

父组件:

<EmailInput
  defaultEmail={this.props.user.email}
  key={this.props.user.id}
/>

可以使用 key 这个特殊的 React 属性。当 key 变化时, React 会创建一个新的而不是更新一个既有的组件,每次 ID 更改,都会重新创建 EmailInput ,并将其状态重置为最新的 defaultEmail 值

更多

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值