目錄
1. 組件render渲染了一個對象, 當state已確定更新但視圖未更新
2. 組件render渲染了一個列表, 當state改變視圖更新異常
3. A和B子組件共用一個父組件state, 此時點擊子組件A按鈕更新了父組件state, 但是子組件B視圖不更新
4. 父子組件同時初始化, 子組件接收的值來自父組件異步獲取的數據
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學習筆記-解決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, 這時候就會導致組件狀態問題。
參考:
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 沒有改變,就不會重新渲染頁面。
參考:
7.當列表循環渲染之後,觸發事件改變事件對應的值, 視圖不更新
還有一種情況是如下, 直接改變源數據發現是沒有變化的, 只有觸發視圖重排纔會有效果
obj.map(item=>{
<span onClick={()=>{item.name=1}}>{item.name}<span>
})
原因:
對象內的數據沒有做監聽
解決辦法:
想辦法觸發視圖重排, 重排方法很多; 我暫時能想到的是添加一個node節點, 再刪除;如果你有其他好辦法好想法可以留言一起學習討論!