標籤:

問一個react更新State的問題?

讀react官網:

狀態更新可能是動態的

// Wrong
this.setState({
counter: this.state.counter + this.props.increment,
});

官網說這種寫法是錯誤的

// Correct
this.setState((prevState, props) =&> ({
counter: prevState.counter + props.increment
}));

這種寫法是正確的

我實在搞不懂為什麼第一個是錯誤的,第二種寫法是正確的,哪位大神能幫忙解釋一下?在哪種需求場景下,會出現上述的情況,最好能寫點代碼解釋下,多謝,大神們指導。


這個問題確實像其他回答評價的那樣,「老生常談」了。

但是有兩點我不是很理解:

  • 為什麼其他回答都是上來就說「React setState 更新是非同步的」?(錯誤的誤導)
  • 為什麼在很多答主本身都並沒有完全理解這個問題的情況下,就「教育」「嘲諷」題主自己查資料、解決問題?

先說第二點,如果所有人都具備親自手動查資料解決問題的能力,那麼社區上是不是就會少太多「愚蠢」的問題和針對幼稚問題的詳盡答案。

作為開發者,我們一定要具備自學自研的能力。同時,時刻都要 be humble,「冷嘲熱諷他人提問,數落他人不會自己查問題解決」不是很好的表現。

「有問題,儘管問」才會有高質量的回答,才會有其他人「自行查詢」解決的前提。

再來說第一點,回到問題的本身。我企圖從 React 官方找到問題的答案:

setState() does not always immediately update the component. It may batch or defer the update until later. This makes reading this.state right after calling setState()a potential pitfall.

Voilà, 準確的用詞是 batch later 或者 defer, 這種表達和我們傳統上所謂的「非同步」不盡相同。另外,人家用詞明顯是 may,因此我們知道這種所謂的「延遲更新」並不 cover 100% cases。換句話說,某些情況下,它也是能夠馬上或者「同步」完成更新的。

那麼,怎麼就像其他答主所說的那樣,一定就是非同步更新了呢?

There is no guarantee that this.state will be immediately updated, so

accessing this.state after calling this method may return the old value.

首先,不保證馬上更新是真的,比如我們試驗這樣的代碼:

function incrementMultiple() {
this.setState({count: this.state.count + 1});
this.setState({count: this.state.count + 1});
this.setState({count: this.state.count + 1});
}

直觀上來看,當上面的 incrementMultiple 函數被調用時,組件狀態的 count 值被增加了3次,每次增加1,那最後 count 被增加了3。但是,實際上的結果只給 state 增加了1。

事實上,

setState 方法與包含在其中的執行是一個很複雜的過程,從 React 最初的版本到現在,也有無數次的修改。它的工作除了要更動 this.state 之外,還要負責觸發重新渲染,這裡面要經過 React 核心 diff 演算法,最終才能決定是否要進行重渲染,以及如何渲染。而且為了批次與效能的理由,多個 setState 呼叫有可能在執行過程中還需要被合併,所以它被設計以延時的來進行執行是相當合理的。

圖片來源於網路,侵刪

但是,你再試試:

componentDidMount() {
document.querySelector("#btn-raw").addEventListener("click", this.onClick);
}
onClick() {
this.setState({count: this.state.count + 1});
console.log("# this.state", this.state);
}
// ......
render() {
console.log("#enter render");
return (
&
&{this.state.count}
&

使用react開發,大家使用什麼IDE工具?JSX語法報錯?
redux中執行dispatch()方法對store不同節點屬性的干擾?
react v16使用flow做類型檢查,Fiber使用typescript做類型聲明以及測試?

TAG:JavaScript | React |