咱们大多数状况下须要getDerivedStateFromProps吗

使用背景

我很不喜欢在代码里写componentWillReceiveProps,由于这样会致使子组件太过灵活,你并不知道什么时候就改掉了子组件的state。可是,当子组件须要根据父组件更新的props中的某个属性来更新自身的state来作到从新渲染子组件时,我又只能鬼使神差的写下这么一段本身都不喜欢的代码:javascript

class Demo extends Component {  
    state = {    
        value: this.props.value  
    };​   
    componentWillReceiveProps(props){    
        if(props.value !== this.state.value){      
            this.setState({value:props.value})    
        }    
        if(this.props.value){      
        // 作一些须要this.props的事 
        }  
    }    
    // ...
}复制代码

这种代码应该在实际React应用中很常见,在新版本的React中,componentWillReceiveProps被标记为unsafe,同时,官方出了一个新的生命周期getDerivedStateFromProps,官宣称配合componentDidUpdate,能够覆盖componentWillReceiveProps的全部用法html

说明书

componentWillReceiveProps能够使用this.props,不只能够作setState操做,还能够和this.props进行比对去作一些平常的方法的操做。java

componentWillReceiveProps(props){  
    if(props.value !== this.state.value){    
        this.setState({value:props.value})  
    }  
    if(this.props.value){   
         // 作一些须要this.props的事  
    }
}复制代码

getDerivedStateFromProps禁止访问this.props,强制指定props只能和state进行比对,能够说是为setState而建立的。react

static getDerivedStateFromProps(props,state){    
    if(props.value !== state.value){      
        return {        
            value:props.value      
        }    
    }    
    return null
}复制代码

而那些须要this.props作的事则经过componentDidUpdate来作,也就解释了上面所说的getDerivedStateFromProps + componentDidUpdate = componentWillReceivePropsbash

componentDidUpdate(){  
    if(this.props.value){    
    // 作一些须要this.props的事  
    }
}复制代码

能够说新的生命周期使得何时作什么事变得更清晰了,经过强制的不暴露this.props来将componentWillReceiveProps拆分红了拥有各自职责的getDerivedStateFromProps和componentDidUpdateapp

这俩只有这一种区别吗?函数

食用测试

咱们分别在父组件的render和子组件的componentWillReceiveProps和getDerivedStateFromProps打印日志性能

父组件测试

class Index extends React.Component {  
    // ...  
    render(){    
        console.log('父组件更新')    
        <Demo value={this.state.value}>  
    }
}复制代码

子组件使用componentWillReceivePropsui

class Demo extends Component {  
    state = {    
        value: this.props.value      
    };​   
    componentWillReceiveProps(props){    
        console.log('componentWillReceiveProps')    
        if(props.value !== this.state.value){      
            this.setState({value:props.value})    
        }  
    }  
    render(){    
        console.log('子组件更新')     
        // ...  
    }
}复制代码

子组件初始化打印结果:

父组件更新
子组件更新复制代码

子组件更新state.value的打印结果:

子组件更新
父组件更新
componentWillReceiveProps
子组件更新复制代码

2.子组件使用getDerivedStateFromProps

class Demo extends Component {  
    state = {    
        value: this.props.value  
    };​  
    static getDerivedStateFromProps(props,state){    
        console.log('getDerivedStateFromProps')    
        if(props.value !== state.value){      
            return {        
                value:props.value      
            }    
        }    
        return null  
    }  
    render(){    
        console.log('子组件更新')     
        // ...  
    }
}复制代码

子组件初始化打印结果:

父组件更新
getDerivedStateFromProps
子组件更新复制代码

子组件更新state.value的打印结果:

getDerivedStateFromProps
子组件更新
父组件更新
getDerivedStateFromProps
子组件更新复制代码

这让咱们更清晰的认识了getDerivedStateFromProps函数,他不只在props变化的时候触发,而是在每次render(state和props更新)时就会触发

不仅是子组件自己的render,当父组件一个无关本组件的state发生了变化,也会触发getDerivedStateFromProps

大多数状况下替代componentWillReceiveProps的方法

当我打算将getDerivedStateFromProps取代个人componentWillReceiveProps时,看到了一篇来自React的官方blog 你可能不须要使用派生 state,虽然是去年的文章了,可是看到依然以为有种想要双击666的感受。

熟悉React的童鞋都知道,key值是否相同是React决定是否从新建立仍是更新组件的缘由。

一样的,咱们能够采用这个原理作咱们刚才的范例。

在咱们的父组件设置好key值:

<Demo key={item.value} callback={changeValue}>复制代码

去掉子组件里的getDerivedStateFromProps/componentWillReceiveProps

每次这个Demo组件的state.value更改,触发了props的更改,咱们以前在getDerivedStateFromProps所作的就是在props更改时同时改掉子组件的state。

如今咱们经过赋值key的方法,使每次key变更时,从新建立Demo组件,这听起来很慢,可是这点的性能是能够忽略的。若是Demo组件树上有很重的逻辑时,建立反而比更新快,由于省略了子组件的diff

大部分状况下,这是处理重置 state 的最好的办法。

相关文章
相关标签/搜索