[zustand] 튜토리얼

강동욱·2024년 3월 24일
0

스토어 생성하기

스토어에는 원시타입, 객체, 함수를 저장할 수 있고 set 함수를 이용해 state를 merge 할 수 있다.

import { create } from 'zustand'

const useStore = create((set) => ({
  bears: 0,
  increasePopulation: () => set((state) => ({ bears: state.bears + 1 })),
  removeAllBears: () => set({ bears: 0 }),
  updateBears: (newBears) => set({ bears: newBears }),
}))

컴포넌트와 연결하기

zustand는 provider를 필요로 하지 않아서 간편하다.

function BearCounter() {
  const bears = useStore((state) => state.bears)
  return <h1>{bears} around here...</h1>
}

function Controls() {
  const increasePopulation = useStore((state) => state.increasePopulation)
  return <button onClick={increasePopulation}>one up</button>
}

Flat updtaes

zustand는 set 함수를 이용해서 새로운 state를 업데이트 한다.

import { create } from 'zustand'

type State = {
  firstName: string
  lastName: string
}

type Action = {
  updateFirstName: (firstName: State['firstName']) => void
  updateLastName: (lastName: State['lastName']) => void
}

const usePersonStore = create<State & Action>((set) => ({
  firstName: '',
  lastName: '',
  updateFirstName: (firstName) => set(() => ({ firstName: firstName })),
  updateLastName: (lastName) => set(() => ({ lastName: lastName })),
}))

function App() {
  const firstName = usePersonStore((state) => state.firstName)
  const updateFirstName = usePersonStore((state) => state.updateFirstName)

  return (
    <main>
      <label>
        First name
        <input
          onChange={(e) => updateFirstName(e.currentTarget.value)}
          value={firstName}
        />
      </label>

      <p>
        Hello, <strong>{firstName}!</strong>
      </p>
    </main>
  )
}

store를 설정할때 state랑 action함수의 타입을 같이 정의할 수 있다.

Deeply nested object

type State = {
  deep: {
    nested: {
      obj: { count: number }
    }
  }
}

만약에 다음과 같이 깊은 상태 객체가 있다면 spread operator로 이용하는 가장 평범한 접근방법이 있다.

 normalInc: () =>
    set((state) => ({
      deep: {
        ...state.deep,
        nested: {
          ...state.deep.nested,
          obj: {
            ...state.deep.nested.obj,
            count: state.deep.nested.obj.count + 1
          }
        }
      }
    })),

하지만 위와같은 방법은 코드가 가독성이 떨어지므로 이에 대한 대안책을 소개하겠다.

immer사용하기

  immerInc: () =>
    set(produce((state: State) => { ++state.deep.nested.obj.count })),

깊은 객체가 있을땐 immer를 사용해서 위와같이 코드를 작성하면 불변성을 유지하면서 가독성이 이전보다 뛰어난 코드를 작성할 수 있다.

profile
차근차근 개발자

0개의 댓글