มาใช้ Zustand ร่วมกับ React + TypeScript กันดีกว่า

React Aug 17, 2023

สวัสดีครับ วันนี้ขอมาเขียนบล็อก วิธีการใช้งาน Zustand ร่วมกับ React.js + TypeScript เผื่อใครไม่รู้ตัว Zustand เป็น State Management library ตัวนึงของ React (ซึ่งมีอีกมากมายในกลุ่มนี้)

Zustand
🐻 Bear necessities for state management in React

ข้อดีของ Zustand

ส่วนตัวผมมองว่ามีข้อดีประมาณนี้

  • มันไม่ยุ่งยากเท่ากับ Redux เขียนและอ่านง่ายกว่า
  • ไม่จำเป็นต้องเอาพวก Context Provider มาหุ้มตัว App หรือ Container เราแบบ Context API
  • เป็น Centralize คล้ายๆ global state

การใช้งาน Zustand ก็ง่ายๆ แค่ติดตั้งผ่าน npm/yarn หรือ pnpm

npm install zustand 

# yarn
yarn add zustand

#pnpm
pnpm add zustand

ตัวอย่าง App Counter ที่ใช้ TypeScript + Zustand

import { create } from 'zustand'

type Store = {
  count: number
  inc: () => void
}

const useStore = create<Store>()((set) => ({
  count: 1,
  inc: () => set((state) => ({ count: state.count + 1 })),
}))

function Counter() {
  const { count, inc } = useStore()
  return (
    <div>
      <span>{count}</span>
      <button onClick={inc}>one up</button>
    </div>
  )
}

จากโค๊ดด้านบน เราจะเห็นว่า

  • เรากำหนด type Store โดยมี count และ inc เป็น function
  • function create ของ zustand เป็น hook function สำหรับสร้าง store ถ้ามองดีๆรูปแบบมันคือ create<T>()(...)
  • ตัว useStore ที่เราได้จาก create เป็น hook ฉะนั้น เราก็สามารถเรียกใช้งานใน Component ของเราได้เลย โดยไม่ต้องมี Provider
const { count, inc } = useStore()
  • ถ้า component นั้นมีการใช้ state ใน store ก็จะทำการ re-render เหมือน state ปกติใน component

Multiple States

สมมติเรามีข้อมูล state ที่เก็บใน store เยอะมากๆ เช่น มีพวก name, score, message เพิ่มเข้าไป

type Store = {
  count: number
  name: string
  score: number
  message: string
  inc: () => void
}

หากเราใช้แบบด้านล่างนี้ มันจะ re-render component ทุกครั้งที่ state เปลี่ยน

const state = useStore()

ส่วนมากจะใช้วิธี state slices เอาแค่ state ที่เราต้องการใช้ใน component นั้นๆ เช่น

const name = useStore(state => state.name)
const message = useStore(state => state.message)

หรือหากใครเคยใช้ mapStateToProps แบบ Redux เราสามารถใช้เป็น single object ได้ โดยใช้ shallow แบบนี้

import { shallow } from 'zustand'

const { name, message } = useStore(
  (state) => ({ name: state.name, message: state.message })
)

// ใน useStore รับ fn ที่รับ state เป็น args แล้ว return เป็น object
// function(state) {
//   return { name: state.name, message: state.message }
// }

References

Zustand Documentation
Zustand is a small, fast and scalable bearbones state-management solution, it has a comfy api based on hooks

Tags

Chai Phonbopit

เป็น Web Dev ทำงานมา 10 ปีหน่อยๆ ด้วยภาษา JavaScript, Node.js, React, Vue และปัจจุบันกำลังสนใจ Web3, Crypto และ Blockchain เขียนบล็อกที่ https://devahoy.com