iT邦幫忙

2025 iThome 鐵人賽

DAY 18
0
Modern Web

重溫 React 官方文件回到最初的起點系列 第 18

Day 18 - 將一系列的 State 更新加入隊列

  • 分享至 

  • xImage
  •  

在昨天的文章,介紹了 state 就像是螢幕快照一樣,一次 render 只會的 state 不會改變,所以我們如果進行三次 setNumber(number + 1) 所更新的 state 也只會有一次,因為這邊的 number 都是 0

import { useState } from 'react';

export default function Counter() {
  const [number, setNumber] = useState(0);

  return (
    <>
      <h1>{number}</h1>
      <button onClick={() => {
        setNumber(number + 1);
        setNumber(number + 1);
        setNumber(number + 1);
      }}>+3</button>
    </>
  )
}

最後更新完顯示的就會是 1,那如果我們同時寫上增加不同的數字會怎麼樣呢:

import { useState } from 'react';

export default function Counter() {
  const [number, setNumber] = useState(0);

  return (
    <>
      <h1>{number}</h1>
      <button onClick={() => {
        setNumber(number + 1);
        setNumber(number + 2);
        setNumber(number + 3);
      }}>+3</button>
    </>
  )
}

最後會發現因為一開始的 state 都是 0,但最後執行的會是 setNumber(0 + 3),所以顯示的值就會是 3。會這樣執行就會講到另一個 React 更新 state 功能,批次更新(batch update)
今天的文章參考官方文章的:

React 批次 state 更新

當我們在 handler 裡面執行 state 更新的時候,React 會等到所有在 handler 裡的程式碼跑過一次後再進行 state 的更新,之後在重新 render 畫面。這就像是餐廳服務員會等到客人點完餐(中間可以改變心意),再把點餐的內容傳到給廚師處理。

這樣的處理可以避免多次觸發 re-render,讓我們的應用程式可以跑得更快。不過 React 橫跨各 handler 來進行 batch 更新,每一次都會是獨立的,像是點擊按鈕。如果第一次按按鈕把表單(form)給關掉(disabled),第二次點擊的時候就不會送出,因為已經關掉了。

在下一次 render 先更新 state 值

如果在下一次 render 前,就先更新 state 的值,譬如說在 handler 裡面,我們可以在 setter 裡面傳入一個根據前一個在序列(queue)裡的 state 計算出的更新後的 state 的 function,會寫成像是 setNumber(n => n + 1),這個意思就是會把 state 更新成前一個 state 值 + 1,因為回傳的是 n + 1,我們也可以做其他處理再回傳。這樣的回傳 function 會告訴 React 對 state 進行處理而不是直接取代。

把我們前面的範例修改一下就會變成:

import { useState } from 'react';

export default function Counter() {
  const [number, setNumber] = useState(0);

  return (
    <>
      <h1>{number}</h1>
      <button onClick={() => {
        setNumber(n => n + 1);
        setNumber(n => n + 1);
        setNumber(n => n + 1);
      }}>+3</button>
    </>
  )
}

這樣這次 +3 的按鈕按下去就會顯示 3 了。
n => n + 1 這個傳進 setter 裡的 function,又叫做 updater function,他在執行的時候會做兩件事:

  1. 把 updater function 加進 queue
  2. 在下一次 render 的時候,React 找到 queue 並且更新最後的 state

剛剛的範例寫成表格就會像是:
https://ithelp.ithome.com.tw/upload/images/20251002/201630244VDcbzjxoL.png

在這邊,updater function 也需要是一個 pure function,不能在裡面有其他 side effect,不然會發生非預期的錯誤。

命名規則

在使用 pure function 的時候,參數是可以自己命名的,因為剛才是 setNumber 的 updater function 所以把使用的前一個 state 命名為 n 代表 number,所以不是全部的 function 都是使用 n 當作參數。我自己的話因為是代表前一個,所以比較通用會使用 prev 代表前一個 state 的意思。可以跟團隊討論看看怎樣才是最適合的命名。

小結

今天介紹了 state 的 batch update,跟 state updater function,希望有讓大家能了解更多關於 state 的更新。
今天的文章告一個段落了,感謝大家耐心地看完,如果有任何問題與建議歡迎跟我說,明天見,晚安。


上一篇
Day 17 - State 當作快照(Snapshot)
下一篇
Day 19 - 更新 State 內的 Object Part 1
系列文
重溫 React 官方文件回到最初的起點20
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言