iT邦幫忙

2021 iThome 鐵人賽

DAY 2
0
Modern Web

用30天更加認識 React.js 這個好朋友系列 第 2

Day2-React Hook 篇-認識 useState

今天我們來認識一個相當常使用的 hook: useState。

語法

const [currentValue, setCurrentValue] = useState(initialValue);
  • currentValue 是存放 state 的值
  • setCurrentValue 是用來設定 state 值
  • initialValue 是 state 的初始值

語法相當的簡單,其概念源自於解構賦值,我們把範例的 useState(0) 印出來看,可以看到 useState 回傳一個陣列,第一個參數是 state 的初始值,第二個名字叫 dispatchAction,意思可以想到是去修改 state 的函式。

範例

import { useState } from 'react';

export default function App() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(pre => pre + 1)}>
        Click me
      </button>
    </div>
  );
}

特性

1. 更新 state 時會 re-render 元件

2. 不會立即更新,像非同步但又不是 Javascript Call stack % Event loop 的那種非同步

由於 react 有 state batch update 的特性,也就是在多次觸發同步事件去更新 state 時,會合併成一次的更新,元件只會重新渲染一次,減少了不必要的渲染。

根據此點特性,state 是透過 batching 去更新值,因此設定新的值給 state 後,馬上 console 印出來的值還是更新前的值。

但非同步事件就不會做 batch,強制 batch 可以使用 ReactDOM.unstable_batchUpdate。

state batch update 範例

那如果要馬上取得更新後的值怎麼做?

解法 1: 多建一個 useEffect

這篇 Andy Chang 大大寫的文章中有提到範例:
https://ithelp.ithome.com.tw/articles/10257994

解法 2: 使用 Custom hook useStateRef

這個還挺好用的,state 結合 ref,馬上就取得更新後的 state 值。
useStateRef(npm 網站)

其他

setCount(count + 1) 和 setCount(prev => prev + 1) 的不同

前者因為 state 還沒有馬上更新就繼續 +1,所以最後加完還是 1,後者是取更新後的 state 繼續加,所以會出現 3。

export default function App() {
  const [count1, setCount1] = useState(0);
  useEffect(() => {
    setCount1(count1 + 1);
    setCount1(count1 + 1);
    setCount1(count1 + 1);
  }, []);

  const [count2, setCount2] = useState(0);
  useEffect(() => {
    setCount2((prev) => prev + 1);
    setCount2((prev) => prev + 1);
    setCount2((prev) => prev + 1);
  }, []);
  return (
    <div>
      Current count1: {count1}
      <!-- 1 -->
      <br />
      Current count2: {count2}
      <!-- 3 -->
    </div>
  );
}

在更新物件、陣列型別的 state,也都是採用後者方式更新

程式碼範例(codesandbox)


上一篇
Day1-鐵人賽大綱 & 為什麼要使用 Hook?
下一篇
Day3-React Hook 篇-認識 useEffect
系列文
用30天更加認識 React.js 這個好朋友32

尚未有邦友留言

立即登入留言