2017-03-17 55 views
1

我有一些代碼,似乎工作,只是不正確。我有一個onChange處理程序,它向其父組件發送一個密鑰和值爲setState()環路狀態,並檢查對象是否存在

_onAttributeChange(key, value) { 
    const changes = this.state.changes; 
    const pushObj = {key: key, value: value}; 
    console.log(pushObj); 
    if (changes.length === 0) { 
     this.setState({changes: changes.concat([pushObj])}); 
    } else { 
     changes.forEach(change => { 
      if (change.key === key) { 
       console.log('Update'); 
      } else { 
       console.log('No update'); 
       this.setState({changes: changes.concat([pushObj])}); 
      } 
     }); 
    } 
} 

您可以從該代碼基於關鍵數值參數看起來像{key: 1, value: 'Some Value'},我創建一個對象看。目標是將數組連接到數組,如果數組的長度爲0.那部分工作正常。 forEach是我遇到問題的地方。我的目標是循環遍歷狀態數組,檢查進入的change.key是否與數組中的鍵匹配,如果有,我想執行更新,否則我想再次連接以將該更改添加到數組。

所以2個問題:

  • 首先,當第一個變化到來時,迴路正常工作,而只會控制檯日誌Update爲使用相同的密鑰每個連續的變化(即1)。當另一個更改進入時,它首先正常工作,並將其連接到數組,然後使用鍵2進行連續更改,它將觸發Update AND控制檯的日誌。

  • 其次,如何在不改變狀態的情況下在循環數組的同時更新更改?

+0

我的回答有幫助嗎?如果確實如此,請考慮將其標記爲「已接受」。如果沒有,請讓我知道我可以如何幫助。 – Chris

+0

@Chris對不起,克里斯。事實上,我前一天患上胃腸感冒,所以直到前幾天我纔回來檢查。我已經接受你的答案,因爲它絕對是解決方案! – Jake

+0

沒問題。很高興我可以幫助:) – Chris

回答

2

答案應該很簡單,只是在狀態的臨時副本上工作,一旦完成後,將副本替換爲您的實際狀態。

_onAttributeChange(key, value) { 
    let changes = this.state.changes.slice(); 
    const pushObj = {key: key, value: value}; 
    console.log(pushObj); 
    if (changes.length === 0) { 
    changes = changes.concat([pushObj]); 
    } else { 
    changes.forEach(change => { 
     if (change.key === key) { 
     console.log('Update'); 
     } else { 
     console.log('No update'); 
     changes = changes.concat([pushObj]); 
     } 
    }); 
    } 
    this.setState({changes: changes}); 
} 

你連續變化遇到的問題是最有可能涉及到的setState()異步特性。每個這樣的調用不僅會導致不必要的重新渲染,而且也會幾乎肯定會以不希望的方式更新您的狀態。

看一看什麼官方文件做出反應說,關於setState()

setState()不會立即發生變異this.state但創建一個 掛起狀態轉變。調用此 方法後訪問this.state可能會返回現有值。沒有 保證同步操作對setState的調用,並且調用可能爲 進行批處理以提高性能。

所以基本上它可能會返回「舊」的狀態值,當你真的想從循環中的上一次迭代更新的。


這裏需要注意的另外一個很重要的事情是,你需要創建你的工作國家財產的副本。否則,你會直接改變狀態,這可能有用,但不鼓勵。

所以基本上總是這樣:爲slice()Object.assign()上MDN

//To copy an array 
let arr = this.state.myArray; //wrong. arr still references myArray 
let arr = this.state.myArray.slice(); //correct 

//To copy an object 
let obj = this.state.myObject; //wrong. obj still references myObject 
let obj = Object.assign({}, this.state.myObject); //correct 

更多信息。

另外,請謹慎使用const。只有當變量必須是不可變的時才使用它。


TL; DR - 永遠做所有的邏輯首先,然後提交您的狀態變化。

+0

在「沒有更新」之後,它應該是行中的'='而不是':'。 – squgeim

+0

@squGEIm好眼睛。謝謝。 – Chris