深入理解 batch update 與 updater function
batch update
setState
的資料更新後會觸發 component re-render,react 會在將所有執行的事件完成後,才會進行 re-render。
在上面的例子中:
-
react 執行 App compoent function 後會產生描述畫面的 React element ,並將這個 React element 產生相對應的 DOM element 渲染到瀏覽器上。
-
在 App component 中初始的 count state 是 0 ,clickCount state 是 0
-
當點擊 button 後會去執行
handleClick
function -
-
當執行到
setCount(1)
時,react 會將這個更新的動作依照順序放到一個代執行計算佇列 (queue)中 -
此時的佇列依序由舊至新有:
setCount(1)
-
此時 count 的值為 0
-
此時 clickCount 的值為 0
-
-
-
當執行到
setCount(3)
時,react 會將這個更新的動作放到佇列 (queue)中 -
此時的佇列由舊至新依序有:
setCount(1)
、setCount(3)
-
此時 count 的值為 0
-
此時 clickCount 的值為 0
-
-
-
當執行到
setCount(5)
時,react 會將這個更新的動作放到佇列 (queue)中 -
此時的佇列由舊至新依序有:
setCount(1)
、setCount(3)
、setCount(5)
-
此時 count 的值為 0
-
此時 clickCount 的值為 0
-
-
-
當執行到
setClickCount((clickCount) => clickCount + 1)
時,react 會將這個更新的動作放到佇列 (queue)中 -
此時的佇列由舊至新依序有:
setCount(1)
、setCount(3)
、setCount(5)
、setClickCount((clickCount) => clickCount + 1) -
此時 count 的值為 0
-
此時 clickCount 的值為 0
-
-
-
執行完所有的事件後,react 會依照最新佇列的順序自動合併相同的
setState
方法,並且只執行最後一次的setState
方法, -
此時 count 的值為 5,
-
此時 clickCount 的值為 1
-
-
更新 state 後才會進行一次 re-render。
batch update 的機制就是 React 會自動將所有的 setState
方法依序合併成一次更新,藉此可以省去每更新一次 state 就進行一次 re-render 的效能問題,也可以避免半成品的資料進行 render。
flushSync
api
大多數的情況下 react 都會自動幫我們處理好 setState
合併更新資料,但如果想要針對某些狀態需要當下就觀察到 DOM element 就可以使用 flushSync
方法,flushSync
可以指定某些 setState
方法不要 batch update,而是立刻 re-render。
但是使用 flushSync
需要注意的是 flushSync
blocking 的,如果 DOM 處理太久會阻擋後續的畫面更新繼續進行,可能會造成畫面卡頓。
updater function
updater function 可以作為參數傳入 setState
方法。
const [count, setCount] = useState(0);
const handleClick = () => {
setCount((prevCount) => prevCount + 1);
//(prevCount) => prevCount + 1 就是 updater function
};
在這個例子中,updater function 會讓 setCount
根據到目前為止的 count
值 prevCount 去計算產生新的 count
值。
需要使用 updater function 的情境
- 需要拿到當下 state 持續做計算
- 可以在子元件中直接去拿到 state 的值