我很不喜歡在代碼裏寫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 的最好的辦法。