© 2025 Sejin Cha. All rights reserved.
Built with Next.js, deployed on Vercel
🐻
zustand 스토어 생성하기 스토어는 훅이다 상태로 원시타입, 객체, 함수(action) 모두 들어갈 수 있음 create 함수로 스토어 생성 생성하는 함수의 매개변수로 set 이 들어가며, 이 것은 상태 내에서 setState 역할을 한다 set 다음에 get도 인자로 들어갈 수 있음 ⇒ 현재 상태를 지칭함
컴포넌트와 스토어를 연결하기 상태를 사용하고 싶은 컴포넌트에서 스토어 훅을 사용하여 상태들을 가져온다 스토어 훅 안에 원하는 상태를 꺼내는 함수를 넣는다 ((state) => state.가져오고싶은상태)
상태 가져오기 모든 상태 가져오기 const state = useBearStore()
⇒ 모든 상태가 변할 때마다 컴포넌트가 업데이트 됨
⇒ state.상태
로 원하는 상태를 가져오거나 구조분해를 사용할 수 있음
원하는 상태만 가져오기 const bears = useBearStore((state) => state.bears)
⇒ strict-equality(일치 비교)를 통해 상태의 변화를 판단
동등성 비교 1. useShallow
객체, 배열 등의 변화를 얕은 비교로 감지한다 즉, 계산된 값(예시에선 상태의 키들)만 비교한다 2. 커스텀 함수 훅을 사용할 때, 인자의 두번째 값으로 커스텀 비교함수를 넣어 동등성을 비교할 수 있다
상태 값을 덮어쓰기 create 에서 쓰는 set의 두번째 인자로 true를 주면, 첫번째 인자인 상태 값으로 상태가 덮어써진다
cf) 기본값은 false, 기존 상태에서 첫번째 인자에 명시된 상태값만 변경된다
non-reactive 상태 getState를 사용해서 비반응형 방식으로 상태에 접근할 수 있다 스토어.getState().상태
: non-reactive하게 상태를 가져옴특정 상태가 변경될 때만 리스너 동작하게 하기 create로 스토어를 생성할 때 내부 함수를 subscribeWithSelector
로 감싸줌
특정 상태를 지정 ⇒ selector: 특정 상태 꺼내는 함수
ref의 값으로 상태를 받기 렌더링에 영향받지 않는 상수이지만, 상태가 업데이트될 때마다 값을 업데이트 하고 싶을 땐 ⇒ useRef + subscribe !!
subscribe : 상태가 변화하면 실행되는 함수
persist import { create } from 'zustand'
const useBearStore = create((set) => ({
bears: 0,
increasePopulation: () => set((state) => ({ bears: state.bears + 1 })),
removeAllBears: () => set({ bears: 0 }),
}))
const useBearStore = create<BearState>((set, get) => ({
bears: 0,
increasePopulation: () => set({ bears: get().bears + 1 }),
}))
function BearCounter() {
const bears = useBearStore((state) => state.bears)
return <h1>{bears} around here ...</h1>
}
function Controls() {
const increasePopulation = useBearStore((state) => state.increasePopulation)
return <button onClick={increasePopulation}>one up</button>
}
const { bears } = useBearStore()
const names = useMeals(useShallow((state) => Object.keys(state)))
const treats = useBearStore(
(state) => state.treats,
(oldTreats, newTreats) => compare(oldTreats, newTreats),
)
const useFishStore = create((set) => ({
salmon: 1,
tuna: 2,
deleteEverything: () => set({}, true),
// clears the entire store, actions included
}))
const useDogStore = create(() => ({ paw: true, snout: true, fur: true }))
const paw = useDogStore.getState().paw //비반응형 방식으로 상태 얻어오기
const unsub1 = useDogStore.subscribe(console.log) //리스너 등록
useDogStore.setState({ paw: false }) //상태 업데이트 => 리스너 동작됨
unsub1() // Unsubscribe listeners
// cf) 기존 방식
function Component() {
const paw = useDogStore((state) => state.paw)
...
import { subscribeWithSelector } from 'zustand/middleware'
const useDogStore = create(
subscribeWithSelector(() => ({ paw: true, snout: true, fur: true })),
)
subscribe(selector, callback, options?: { equalityFn, fireImmediately }): Unsubscribe
// paw가 변경됐을 때
const unsub2 = useDogStore.subscribe((state) => state.paw, console.log)
// 두번째 인자 함수에서 바뀐 상태와 이전 상태를 받을 수 있음
const unsub3 = useDogStore.subscribe(
(state) => state.paw,
(paw, previousPaw) => console.log(paw, previousPaw),
)
// 세번째 인자로 동등성 함수를 받을 수 있음
const unsub4 = useDogStore.subscribe(
(state) => [state.paw, state.fur],
console.log,
{ equalityFn: shallow },
)
// 옵션으로 즉시 실행 할 수 있게 지정할 수 있음
const unsub5 = useDogStore.subscribe((state) => state.paw, console.log, {
fireImmediately: true,
})
const useScratchStore = create((set) => ({ scratches: 0, ... }))
const Component = () => {
const scratchRef = useRef(useScratchStore.getState().scratches)
useEffect(() => useScratchStore.subscribe(
state => (scratchRef.current = state.scratches)
), [])
...
useEffect로 컴포넌트 생성시 subscribe를 함