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)


<<:  Day 01:新手视角

>>:  DAY 01 : 让企业拥有真正属於自己的ERP

Day 29 - 用 canvas 与 fabricjs 做文件签名(下)

接续 昨天完成了材料建立,今天就用 fabricjs 来做两者的合并 fabricjs 使用 fab...

Day 19 Onchange v.s. readonly

Odoo 的onchange 有些特别要注意的地方, 像是onchange会影响到的栏位都要写入XM...

DAY 22 制作 Nav Bar - Hamburger

接下来要完成的是打开 menu 内容的 hamberger,就是『 三 』这个符号,之前的 font...

Django template - javascript变数含safe filter

这边有一个javascript变数: var subtitles = {{ json_dual }}...

【第二十七天 - XSS Lab(2)-5】

Q1. XSS Lab(2)-5 题目:https://alf.nu/alert1 Fruit 题目...