componentWillReceiveProps使用时的问题

componentWillReceiveProps使用时的问题

componentWillReceiveProps是在render之前执行的函数,在函数的内部会接收nextProps参数,存储着本次更新的数据的值,this.props存储上一次更新的数据的值,可以通过比较两数据值得不同来进行setState更新组件的状态,不会触发额外的render。

场景如下:要实现一个功能,订购页面引入子组件游客信息,可以通过新建,删除,编辑子组件的游客信息,父组件也可以批量导入来改变游客信息,每次变更,游客信息的第一行的数据都会被同步到联系人的位置。
在这里插入图片描述
实现思路,子组件每次新建或修改或编辑都会引发联系人的变化,也会引发nextProps里面value的变化,因此在componentWillReceiveProps函数中获取到更改,更新给父组件。
无限死循环
在componentWillReceiveProps中,当需要对父组件的状态进行更新的时候,一定要判断更新时的状态,也就是更新条件,不然会重复的render,因为在componentWillReceiveProps中调用父组件的函数,更新了父组件的状态,父组件更新子组件也会更新,子组件更新的时候又去调用父组件的函数,如此下去无限循环。如下刚开始没有做判断,只要value也就是table数据存在,就取第一行数据,更新父组件的联系人,此时造成无线循环。例如如下代码。

 componentWillReceiveProps(nextProps) {
   if('value' in nextProps ){
     if( nextProps.value.length != 0){
       this.props.handlecantact(nextProps.value[0].name, nextProps.value[0].telephone);
     }
 }

之后进行修改,分为两种情况,一种情况是添加联系人,导入联系人,删除联系人,这种使游客数目发生变更,也就是当前value的长度不等于上一次value的长度时,进行联系人的更新。另外一种情况是编辑游客信息,联系人数目相等但是内容发生了改变时进行更新联系人信息。

 componentWillReceiveProps(nextProps) {
   if('value' in nextProps ){
     if(nextProps.value.length != this.props.value.length && nextProps.value.length != 0){
       this.props.handlecantact(nextProps.value[0].name, nextProps.value[0].telephone);
     }
     if(nextProps.value.length == this.props.value.length && nextProps.value.length != 0 && this.props.value.length!=0 ){
       if(nextProps.value[0].name != this.props.value[0].name || nextProps.value[0].telephone != this.props.value[0].telephone )
       this.props.handlecantact(nextProps.value[0].name, nextProps.value[0].telephone);
     }
   }
 }

componentWillReceiveProps中nextProps和this.props值相等
componentWillReceiveProps并不是每次props改变的时候被调用,有时候就算是props没有改变也会被调用,在我遇到的场景,componentWillReceiveProps有时会因为父组件更新一些状态而被调用,但是子组件是没有更新状态的,当编辑子组件的联系人更改某一个之后,通过this.props.onChange()将变更传递到父组件,父组件在传递回给子组件,结果发现两次更改的nextProps.value和this.props.value相等,但是实际已经更改了内容,这时候我百思不得其解,后来发现因为是通过 this.props.onChange(this.state.data)方式将变更传递给父组件,也就是说父组件获取的OrderPeople组件的value此时是this.state.data,当修改其某一个游客的值得时候,刚开始采用如下代码,这里[…this.state.data]采用的是浅拷贝,因此当改变newData的值得时候,也会改变this.state.data的值,导致react捕获不到这种变更,使得nextProps.value和this.props.value相等。

handleFieldChange(e, fieldName, key) {
    const newData = [...this.state.data];
    const target = this.getRowByKey(key);
    if (target) {
        target[fieldName] = e.target.value;
        this.setState({  data: newData });

    }
}
getRowByKey(newData,key) {
  return this.state.data.filter(item => item.key === key)[0];
}

解决问题的办法就是,采用数组的深拷贝,完全新建一个数组,在新数组上进行操作,在进行setState操作更新子组件状态和this.props.onChange()更新父组件状态,react就会捕获到这种变更。

handleFieldChange(e, fieldName, key) {
    const newData = JSON.parse(JSON.stringify(this.state.data));
    const target = this.getRowByKey(newData,key);
    if (target) {
        target[fieldName] = e.target.value;
        this.setState({  data: newData });

    }
}
getRowByKey(newData,key) {
  return newData.filter(item => item.key === key)[0];
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值