iT邦幫忙

2024 iThome 鐵人賽

DAY 11
0
Modern Web

現在就學React.js 系列 第 11

updater function 更新 state - Day11

  • 分享至 

  • xImage
  •  

https://ithelp.ithome.com.tw/upload/images/20240925/20159895uPy07HTIoD.png

昨日提及到使用到 useState 時,當 state 有變動時,就會觸發元件重新渲染,更新畫面。

當有個情境是基於 state 原有的值去計算新值並連續用 setState 來更新時,我們會怎麼做呢?
來看下方的範例,點擊按鈕後會連續累加+1兩次。預計點擊按鈕後,會讓 count 的值從 0 更改為 2。

import React, { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);

  const handleClick = () => {
    setCount(count + 1);
    setCount(count + 1);
  };

  return (
    <div>
      <p>當前計數:{count}</p>
      <button onClick={handleClick}>增加兩次Count</button>
    </div>
  );
}

export default Counter;

但實際按下去後,count的值並沒有變成 2 ,而是 1 ,為何會這樣呢?
主要的原因是 React 的 batch update 機制。

批次更新機制(Batching Updates)

在 React 中,為了提升效能,React 會將多個狀態更新合併為一個批次處理,避免多次不必要的重新渲染。這通常發生在事件處理中,例如在同一個按鈕點擊事件中連續呼叫多次 setState

相關的原理過程,可參考:[Day 14] 以 functional updater 來呼叫 setState - iT 邦幫忙::一起幫忙解決難題,拯救 IT 人的一天 (ithome.com.tw)

那今天想要在同個按鈕連續呼叫多次 setState 可以如何做呢?
解決這種需求方式,就是改以 updater function 的形式來進行 setState 的呼叫。

React Updater function

Updater function 是一種用來更新 state 的方式,
允許我們傳入一個函式作為 setState 的參數。
這個函式會接收前一次的 state 值,並根據該值來更新狀態。

setCount(prevValue => prevValue + 1);

updater function 能夠保證每次更新時使用的都是最新state
而不是呼叫 setState 當下的 state 值。
這能夠避免競態條件(race condition)和批次更新(batching)引發的問題。

將上述案例更改為 updater function

import React, { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);

  const handleClick = () => {
    // 使用  updater function,將前一個狀態值傳入
    setCount((prevCount) => prevCount + 1);
    setCount((prevCount) => prevCount + 1);
  };

  return (
    <div>
      <p>當前計數:{count}</p>
      <button onClick={handleClick}>增加兩次</button>
    </div>
  );
}

export default Counter;
  • updater function 的更新機制:當使用 setCount((prevCount) => prevCount + 1) 時,
    React 會將最新的 count 值傳入 prevCount,這樣就確保每次更新都是基於最新的狀態值。
  • 每次更新都是獨立的:我們在同一個事件中多次呼叫 setCount,每次更新都會基於前一次的結果,最後 count 會正確地增加兩次。

updater function 的使用時機

  1. 多次連續更新狀態
    當需要在同一個事件中多次更新狀態時,例如像計數器的應用,
    updater function 確保每次更新都是基於最新的狀態。

    setCount((prevCount) => prevCount + 1);
    setCount((prevCount) => prevCount + 1);
    
  2. 依賴前一個狀態的更新
    當你的狀態更新邏輯需要依賴於前一個狀態的值時,例如逐步累加或倒數計…

    setItems((prevItems) => prevItems + 1);
    
  3. 避免競態條件
    當多個狀態更新幾乎同時發生時,容易產生競態條件。如果每次更新都依賴於一個靜態值,而不是動態計算的結果,那麼可能會導致更新錯誤。使用 updater function,可以有效避免這些競態條件。

結論

Functional Updater 是 React 中用來更新狀態的一個工具,特別適合用在需要依賴於前一個狀態值的情境中使用。它不僅能夠避免批次更新和競態條件問題,還能確保狀態的每次更新都是基於最新的值。

參考資料:

後記

本文將會同步更新到我的部落格

黃禎平 – Medium


上一篇
第一個hook -useState - Day 10
下一篇
再探 Props 與 State - Day12
系列文
現在就學React.js 31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言