簡體   English   中英

為什么直接變異 state 時 React 會更新?

[英]Why does React update when directly mutating state?

在下面的示例中,我在 React 中使用 ES6 Map 作為 state 值:

 class App extends React.Component { constructor(props) { super(props); const results = new Map(); results["group1"] = [{ value: "..." }, { value: "..." }]; this.state = { results }; } onUpdateClick(i) { this.state.results["group1"][i].value = i; this.setState({}); } onResetClick(i) { this.state.results["group1"][i].value = "..."; this.setState({}); } render() { const { results } = this.state; return ( <div> {results["group1"].map((r, i) => ( <div> {r.value}&nbsp; <button onClick={e => this.onUpdateClick(i)}>update</button> <button onClick={e => this.onResetClick(i)}>reset</button> </div> ))} </div> ); } } ReactDOM.render(<App />, document.getElementById("container"));
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script> <div id='container'></div>

當你點擊按鈕時,我直接更新 Map,就地,然后調用 setState 沒有 arguments。 我不制作 map 的克隆/深拷貝。 根據我對 React 文檔的理解,這應該不起作用,並且在文檔中明確警告:

永遠不要突變 this.state 直接調用 setState() 可能會替換您所做的突變。 將 this.state 視為不可變

https://reactjs.org/docs/react-component.html#state

文檔還 state 比較淺,所以用空的 object 調用應該肯定不會導致合並,因此不會重新渲染?

為什么這個例子有效?

(我還應該注意,我也使用 React v16.9.0 重現了這種行為)

編輯:我還想指出(因為許多答案是指我傳遞一個空對象的事實)如果我像這樣調用 setState 組件將被重新渲染(和更新):

this.setState({ results: this.state.results })

這似乎不應該導致重新渲染

來自文檔: setState

除非 shouldComponentUpdate() 返回 false,否則 setState() 將始終導致重新渲染。

這意味着this.setState({}); 無論您是否將更改作為參數傳遞,都會導致重新渲染

你錯了:

this.setState({}); // this will do nothing.

您期望 state 應更新為空 object。 但事實並非如此。

當您使用 setState 方法時,它期望屬性更新。 但是由於您沒有向 setState 提供任何屬性,因此它什么也不做。 但它仍會按 setState 的性質重新渲染您的組件。

更新:對您的查詢

編輯:我還想指出(因為許多答案是指我傳遞一個空對象的事實)如果我像這樣調用 setState 組件將被重新渲染(和更新):

this.setState({ results: this.state.results })

這似乎不應該導致重新渲染

當您嘗試使用完全相同的 state 更新 state 時,React 內部聲明它類似於this.state.results 所以,沒有什么可以重新渲染的。 但是當你使用空的 object 的 setState 時,React 將 flash 和它的 state 發生重新渲染。

文檔中閱讀此注釋:

筆記

避免將 props 復制到 state 中:這是一個常見錯誤:

constructor(props) {
 super(props);
 // Don't do this!
 this.state = { color: props.color };
}

問題是它既是不必要的(您可以直接使用this.props.color代替),並且會產生錯誤(對 color 道具的更新不會反映在狀態中)。

根據文檔,除非 shouldComponentUpdate() 返回 false,否則setState() 將始終導致重新渲染 您可以將render() function 視為創建 React 元素樹 在下一次 state 或 props 更新中,render() function 將返回不同的 React 元素樹(虛擬 DOM )。

在任何時候, React 庫都會維護兩個 Virtual DOM 副本

觸發 setState() 請求時,React 會創建一個新樹,其中包含組件中的反應性元素(以及更新的 state )。 此樹用於通過將組件的 UI 與前一個樹的元素進行比較來確定組件的 UI 應如何更改以響應 state 更改。

虛擬 DOM 然后通過稱為協調的過程與真實 DOM 同步。

至於突變,不進行直接突變可以避免項目中出現不必要的錯誤,因為setState() 是異步的,這意味着您不能期望 setState 立即更新 state(它是分批更新的),因此任何先前的突變都可以被之前的 setState state 更新操作覆蓋.

參考-

當調用this.setState時,基本上 React 會將我們傳遞給這個 function 的參數與舊的this.state ,以產生一個新的 state 值。 例如:

this.state = Object.assign({}, this.state, passedParam);

所以在上面的片段中,每次你調用this.setState({}); 一個新的 state object 已創建,它使組件重新渲染。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM