iT邦幫忙

2023 iThome 鐵人賽

DAY 15
0
Modern Web

30 days of React 系列 第 15

Day 15 - React 渲染:排隊任務

  • 分享至 

  • xImage
  •  

目前我們掌握了 React 渲染的機制,也就是渲染會經過的三個階段,也了解到在 re-rendering 的過程中發生了什麼事情。還沒完,今天要來學習「排隊任務」的機制。

複習一下「快照」

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>
    </>
  );
}

這個程式碼的按鈕沒辦法透過點擊一次就達到「+3」的值,而是只會「+1」。這是因為在快照的當下,起始值都是 0,而他們都的意涵都是「起始值為 0 請 React 在下一次渲染中+1」。

這邊需要學習一個重要的觀念:React 在渲染時採批次處理。也就是說,React 會等待所有的程式碼執行,再來更新 state。這樣的概念也被稱作batching。

就像我們在餐廳點餐,服務生會等待我們一次點完,再請廚房製作一樣。在這邊等於在同一次渲染(點餐)中講了三次一樣的指令,因此下一次渲染會做的事情就是「0+1」。

要注意的是雖然內容都是一樣的,但它所代表的意義是「替代(replace)」的概念,讓我們稍微改變一下程式碼:

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

按鈕點擊後數值會加多少呢?因為剛剛提到替代的概念,也就是說這邊我們做的事情等於是告訴 React

「請幫我由起始值+1」

不不不

「還是幫我+2 好了」

不不不

「果然還是+3」

所以在下一次渲染中,將是最終結果的+3。

回歸到原始的程式碼,如果要達到點擊一次就將數值 +3 該怎麼做呢?

updater function

雖然也可以透過更改追加的數值來達到這個目的,

假設我們還是想要透過在「下一次」渲染前,透過複數次更新 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>
    </>
  );
}

一開始的程式碼在 setNumber 裡傳入「值」而這也是「替代」的概念,換個思考我們請 React 在同一次渲染中做三件事看看。可以透過傳入依據一連串(batch)的工作任務中中前一個狀態來計算下一個狀態的 function 來達到這個目的。而這樣子的 function 也可以稱作updater function。透過 updater function 讓計算與執行中的 state 的值產生了連結。

因為 batching 的機制,React 這時候了 2 件事:

  1. React 按順序依序等程式碼執行
  2. React 確認要執行的東西,並更新 state

這樣子我們即可達到透過複數次更新 state 來獲得點擊一次即+3 的結果。

讓我們再比較這二者之間的差異

第一段程式碼:顧客想點一道菜,但在訂單上重複改口說了三次相同的菜。即使他改口了三次,服務生最終只會處理一份這道菜的訂單,所以最終只有一份。

第二段程式碼:顧客想點三道一樣的菜,所以他點了三道,每個菜都是獨立的。這樣服務員會在該次點餐處理三份,所以上菜的時候就會有三道。

綜合點餐

<button onClick={() => {
  setNumber(number + 5);
  setNumber(n => n + 1);
}}>

像這樣子,雖然是綜合點餐,但邏輯相同,遵循 batching 的概念,答案就出來了。答案走這

參考資料

  • React 官方文件:Queueing a Series of State Updates

上一篇
Day 14 - React 的渲染機制以及 state 的過程
下一篇
Day 16 - 在 state 中更新物件
系列文
30 days of React 30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言