3 回答

TA貢獻2019條經驗 獲得超9個贊
我在做React。
TLDR:
但是你可以相信React可以按照要求setState的順序更新狀態嗎
相同的組件?
是。
不同的組件?
是。
該訂單的更新總是尊重。是否在它們之間看到中間狀態取決于您是否在批處理中。
當前(React 16和更早版本),默認情況下僅批處理React事件處理程序中的更新。有一個不穩定的API可以在極少數情況下在需要時強制在事件處理程序之外進行批處理。
在未來的版本中(可能是React 17及更高版本),React默認會批處理所有更新,因此您無需考慮這一點。與往常一樣,我們將在React博客和發行說明中宣布對此所做的任何更改。
理解這一點的關鍵是,無論setState()您在React事件處理程序中執行了多少個組件中的多少次調用,它們都將在事件結束時僅產生一次重新渲染。這對于大型應用程序性能良好至關重要的,因為如果Child與Parent每個呼叫setState()處理click事件的時候,你不想重新渲染Child兩次。
在您的兩個示例中,setState()調用都在React事件處理程序中進行。因此,它們總是在事件結束時一起刷新(并且您看不到中間狀態)。
更新總是按照發生的順序進行淺層合并。因此,如果第一個更新為{a: 10},第二個為{b: 20},第三個為{a: 30},則渲染狀態將為{a: 30, b: 20}。對相同狀態鍵的更新(例如,a在我的示例中)總是“獲勝”。
this.state當我們在批處理結束時重新呈現UI時,將更新該對象。因此,如果您需要基于先前的狀態(例如增加計數器)來更新狀態,則應使用setState(fn)為您提供先前狀態的功能版本,而不是從中讀取this.state。如果您對此原因感到好奇,我會在此評論中對其進行深入解釋。
在你的榜樣,我們也不會看到“中間狀態”,因為我們是一個作出反應事件處理中在啟用配料(因為響應“知道”什么時候我們退出該事件)。
但是,在React 16和早期版本中,默認情況下,在React事件處理程序之外都沒有批處理。因此,如果在您的示例中,我們使用AJAX響應處理程序而不是handleClick,則每個處理程序setState()都會在發生時立即進行處理。在這種情況下,是的,您會看到一個中間狀態:
promise.then(() => {
// We're not in an event handler, so these are flushed separately.
this.setState({a: true}); // Re-renders with {a: true, b: false }
this.setState({b: true}); // Re-renders with {a: true, b: true }
this.props.setParentState(); // Re-renders the parent
});
我們意識到,根據您是否在事件處理程序中,行為會有所不同,這很不方便。這將在以后的React版本中更改,該版本默認情況下將批處理所有更新(并提供選擇加入的API以同步刷新更改)。在我們切換默認行為(可能在React 17中)之前,有一個可用于強制批處理的API:
promise.then(() => {
// Forces batching
ReactDOM.unstable_batchedUpdates(() => {
this.setState({a: true}); // Doesn't re-render yet
this.setState({b: true}); // Doesn't re-render yet
this.props.setParentState(); // Doesn't re-render yet
});
// When we exit unstable_batchedUpdates, re-renders once
});
內部React事件處理程序都被包裝,unstable_batchedUpdates這就是為什么默認情況下對它們進行批處理的原因。請注意,將更新打包unstable_batchedUpdates兩次是無效的。當我們退出最外部的unstable_batchedUpdates調用時,將刷新更新。
該API是“不穩定的”,即默認情況下啟用批處理后我們將其刪除。但是,我們不會在次要版本中將其刪除,因此在某些情況下,如果需要在React事件處理程序之外強制執行批處理,則可以放心地使用它直到React 17。
綜上所述,這是一個令人困惑的話題,因為默認情況下,React僅在事件處理程序中進行批處理。這將在將來的版本中更改,并且行為將變得更加簡單。但是解決方案不是少批處理,而是默認情況下多批處理。那就是我們要做的。

TA貢獻1790條經驗 獲得超9個贊
這實際上是一個非常有趣的問題,但答案應該不會太復雜。在媒體上有一篇很棒的文章有答案。
1)如果這樣做
this.setState({ a: true });
this.setState({ b: true });
我不認為會出現的情況下a會true和b會false因為配料。
但是,如果b取決于,a則確實可能存在無法獲得預期狀態的情況。
// assuming this.state = { value: 0 };
this.setState({ value: this.state.value + 1});
this.setState({ value: this.state.value + 1});
this.setState({ value: this.state.value + 1});
處理完所有上述調用后,this.state.value將為1,而不是您期望的3。
這是在文章中提到的: setState accepts a function as its parameter
// assuming this.state = { value: 0 };
this.setState((state) => ({ value: state.value + 1}));
this.setState((state) => ({ value: state.value + 1}));
this.setState((state) => ({ value: state.value + 1}));
這會給我們 this.state.value === 3
添加回答
舉報