มาใช้ Zustand ร่วมกับ React + TypeScript กันดีกว่า
สวัสดีครับ วันนี้ขอมาเขียนบล็อก วิธีการใช้งาน Zustand ร่วมกับ React.js + TypeScript เผื่อใครไม่รู้ตัว Zustand เป็น State Management library ตัวนึงของ 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
