React 之 state 數據改變頁面不更新未重新渲染的 7 種情況 及 解決辦法

目錄

1. 組件render渲染了一個對象, 當state已確定更新但視圖未更新

2. 組件render渲染了一個列表, 當state改變視圖更新異常

3. A和B子組件共用一個父組件state, 此時點擊子組件A按鈕更新了父組件state, 但是子組件B視圖不更新

4. 父子組件同時初始化, 子組件接收的值來自父組件異步獲取的數據

5. 調用方法中state更新了, 但實時拿到的值還是舊的

6. 在redux中修改state頁面未更新

7.當列表循環渲染之後,改變當前item頁面數據不變

 


1. 組件render渲染了一個對象, 當state已確定更新但視圖未更新

代碼:

// 錯誤方式
const obj = this.state.obj;

obj.forEach((e) => {
        xxxxx //省略的代碼是改變了對象的值
});

this.setState({
    obj
});

解決辦法: 淺拷貝方式獲取對象並修改再賦值。

// 正確方式
const obj = [...this.state.obj];

obj.forEach((e) => {
        xxxxx //省略的代碼是改變了對象的值
});

this.setState({
    obj
});

原因: 對象數組是引用方式 ,對於react來說它的值都是地址(涉及到tree diff),因爲沒有被重新賦值(地址沒有改變),所以 react 會認爲仍然是之前的元素(element),則不更新視圖。

參考: 

react更新state後視圖沒有變化

react學習筆記-解決react修改state對象,頁面不刷新問題

 


2. 組件render渲染了一個列表, 當state改變視圖更新異常

代碼:

{this.state.string.split('').map((item,index)=><p key={index}>item</p>)}
//其中this.state.string = '1' 且每秒鐘 +1 ,此時頁面視圖未發生變化

解決辦法: key={index}改成key={item+index}。

原因: key是唯一的. 而1和10在split後是[1]和[1,0],他們都共有1, 這時候就會導致組件狀態問題。

參考: 

 react列表渲染時爲什麼儘量不要把索引設置爲key值

 


3. A和B子組件共用一個父組件state, 此時點擊子組件A按鈕更新了父組件state, 但是子組件B視圖不更新

解決辦法: 同上(2)。

原因: 同一個頁面調用同的組件(出現問題的組件)的key都用了index, 也會導致組件狀態問題。

 


4. 父子組件同時初始化, 子組件接收的值來自父組件異步獲取的數據

場景:

初始化 state.value=' ',

componentDidMount時, 父組件異步獲取數據賦給state.value,

而子組件一同初始化componentDidMount中拿到的state.value還是空的。

解決辦法:

// render中判斷state.value不等於空,再加載子組件即可
render() {
    return (
        { this.state.value? <subComp value={this.state.value}>我是子組件</subComp> : '' }      
    );
}

原因: 因爲子組件已經componentDidMount渲染完成了, 父組件異步獲取數據就沒辦法拿到。

*拓展:  貌似componentWillReceiveProps是符合需求的, 但是我用過幾次有出現問題搞不定需求就沒再用了。

 


5. 調用方法中state更新了, 但實時拿到的值還是舊的

代碼:

//默認string等於''
this.setState({
    string: '123'
})
console.log(this.state.string)//''

解決辦法:

this.setState({
    string: '123'
},()=>{
    //setState後的回調
    console.log(this.state.string)//'123'
})

 原因: react還沒更新state, 打印就執行完畢了。

 


6. 在redux中修改state頁面未更新

解決辦法:  請檢查你的state是不是直接改變原state的, 記住不要直接修改state。

原因:  reducer 中 state 是引用, 在 reducer 中改變 state 是錯誤的, 雖然 store 裏面的 state 是改變了,但是 react - redux 會認爲dispatch 前後的 state 沒有改變,就不會重新渲染頁面。

參考:

react State改變,頁面卻沒有改變

state 更新了,組件卻沒有更新

 


7.當列表循環渲染之後,觸發事件改變事件對應的值, 視圖不更新

還有一種情況是如下, 直接改變源數據發現是沒有變化的, 只有觸發視圖重排纔會有效果

obj.map(item=>{
    <span onClick={()=>{item.name=1}}>{item.name}<span>
})

原因: 

對象內的數據沒有做監聽

解決辦法:

想辦法觸發視圖重排, 重排方法很多; 我暫時能想到的是添加一個node節點, 再刪除;如果你有其他好辦法好想法可以留言一起學習討論!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章