我很不喜欢在代码里写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
当我打算将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 的最好的办法。