關于getDerivedStateFromProps填坑記錄
項目場景
今天又來填一個坑?。。?!
問題描述
最近寫的react項目中用到getDerivedStateFromProps ,這可把我折騰壞了,先說說我想實現的目標吧,在一個組件中當它的props發(fā)生變化時,組件需要重新獲取對應的數據刷新頁面,一開始我想到的是getDerivedStateFromProps不是能監(jiān)聽到props的變化嗎,
我就直接在這個函數中調用獲取數據的方法,這里要注意getDerivedStateFromProps是靜態(tài)方法不能用this直接調用組件中的方法,就想起上次看了一篇博客博主用的是new一個新的組件(下面會具體介紹),
讓這個組件去調用組件中的方法,本來感覺有救了但是這又掉入另一個坑,如果只是想調用一些方法去實現簡單的console.log(),這完全沒問題,
但是想去修改這個組件的數據就有問題了,然后就繞過這個坑想想其他法子,最終通過一些自己都覺得復雜的過程實現了,但是對我來說這肯定不行,然后又去找了許多資料最后通過初始值和 key 值來實現 prop 改變 state ,
好了接下來好好介紹下。
前言
我們先來嘮叨嘮叨getDerivedStateFromProps的一些注意點
1、在用getDerivedStateFromProps時可能出現這樣的問題
Can’t call setState on a component that is not yet mounted.
This is a no-op, but it might indicate a bug in your application. Instead, assign to this.state directly or define a state = {}; class property with the desired state in the *** component.
這是提示我們不能再一個組件尚未mounted時調用 setState() 方法,這是一個空操作,但是可能會導致bug,因為我們的getDerivedStateFromProps方法在mounted執(zhí)行前會執(zhí)行一次,但是在mounted執(zhí)行完之前你是不能調用setState方法,但是可以通過return{}去修改state的值(這是這個方法的本質我就多不說了)
2、在這個方法中不能用this,因為這是個靜態(tài)方法
3、出現死循環(huán)這是使用這個生命周期的一個常見 bug,我們來看的例子
Class ColorPicker extends React.Component {
state = {
color: '#000000'
}
static getDerivedStateFromProps (props, state) {
if (props.color !== state.color) {
return {
color: props.color
}
}
return null
}
... // 選擇顏色方法
render () {
.... // 顯示顏色和選擇顏色操作
}
}現在我們可以用這個顏色選擇器來選擇顏色,同時我們能傳入一個顏色值并顯示。
但是這個組件有一個 bug,我們傳入一個顏色值后它能正確顯示,但是再使用組件內部的選擇顏色方法,我們會發(fā)現顏色不會變化,一直是傳入的顏色值這是為什么呢?
我們聯系下react執(zhí)行更新的條件當組件的props或者state發(fā)生變化時,組件就會重新重新執(zhí)行一遍更新的生命周期函數,在16^4中setState 和 forceUpdate就會觸發(fā)更新,所以 return { color: props.color}后state會發(fā)生改變又會走 getDerivedStateFromProps 方法,并把 state 值更新為傳入的 prop,我們來修理修理,加一個preColor去保存新的color如果上次的preColor和這次props中的color相同就不需要更新
Class ColorPicker extends React.Component {
state = {
color: '#000000',
preColor: ''
}
static getDerivedStateFromProps (props, state) {
if (props.color !== state.preColor) {
return {
color: props.color
prevPropColor: props.color
}
}
return null
}
... // 選擇顏色方法
render () {
.... // 顯示顏色和選擇顏色操作
}
}代碼展示
下面進去我們的主題了,這是我的父組件,子組件通過子路由的形式放到父組件中
<div className={Css['goods-content']}>
<Switch>
<Route path={config.path+"goods/classify/items"} component={GoodsItems}></Route>
</Switch>
</div>這是我子組件中的getDerivedStateFromProps方法,我們先來看看通過new一個新的組建區(qū)調用函數(這里我不做上面第三個問題的bug處理了)這里我調用了一個打印函數
static getDerivedStateFromProps(newProps,preState)
{
new GoodsItems(newProps).console();
return null;
}
console(){
console.log("111")
}
這里我們看到可以正確打印,但是我們現在城市去改變組件中的值
this.state = {
aGoods: [],
cid:null,
precid:null,
num:1
}
this.sum=0;
static getDerivedStateFromProps(newProps,preState)
{
new GoodsItems(newProps).change();
return null;
}
change(){
this.setState({
num:2
},()=>{
console.log("num1: ",this.state.num)
})
this.sum=this.sum+1;
console.log("num2: ",this.state.num)
console.log("sum: ",this.sum)
}
我們可以看到num1沒輸出,每次num2都是1和sum都是1,這是因為每次都是new了一個新的組件改變的是新組建的值,并不影響原來的組件,所以不能用來改變state的值。
我不賣關子了直接上解決方案。
解決方案
我們將子組件直接放到父組件上,不使用子路由,然后給子組件加上一個key指,每次子組件需要更新時就將key值改變,這樣的話就相當于重新加載了一個新的子組件而不是僅僅去更新數據
我們看代碼:
<div className={Css['goods-content']}>
<GoodsItems aGoods={this.state.aGoods ? this.state.aGoods: ''} key={this.state.cid}/>
</div>這里我們也可以將數據傳入,子組件在mounted時候進行setState修改數據
這是官網的解釋

總結
以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
淺談react-native熱更新react-native-pushy集成遇到的問題
下面小編就為大家?guī)硪黄獪\談react-native熱更新react-native-pushy集成遇到的問題。小編覺得挺不錯的,現在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-09-09
Electron整合React使用搭建開發(fā)環(huán)境的步驟詳解
這篇文章主要介紹了Electron整合React使用搭建開發(fā)環(huán)境,本文分步驟給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值 ,需要的朋友可以參考下2020-06-06

