咱們大多數狀況下須要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 的最好的辦法。

相關文章
相關標籤/搜索