작고 빠르며 확장 가능한 상태 관리 솔루션.
docs 최상단에 제공된 zustand 사용법(에 타입 지정을 직접 추가함)
typeScript 가이드 : https://github.com/pmndrs/zustand/blob/main/docs/guides/typescript.md
zustand/docs/guides/typescript.md at main · pmndrs/zustand
🐻 Bear necessities for state management in React. Contribute to pmndrs/zustand development by creating an account on GitHub.
github.com
(store 생성)
기본형, 객체, 함수 무엇이든 들어올 수 있으며
set 함수는 상태를 병합한다( The set function merges state.)
import { create } from 'zustand'
type State = {
bear: number;
}
type Actions = {
increasePopulation: (state: number) => void;
removeAllBears : (state: number) => void;
updateBears: (newBears: number) => void;
}
const useStore = create<State & Actions>((set) => ({
bear: 0,
increasePopulation: () => set((state) => ({ bears: state.bears + 1 })),
removeAllBears: () => set({ bears: 0 }),
updateBears: (newBears) => set({ bears: newBears }),
}))
이후 component들을 바인딩
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>
}
const state = useStore()
이와 같이 모든 구성 요소를 가져오는 것도 가능하지만,
state가 변경될때마다 모든 구성 요소가 업데이트되기 때문에 권장되지 않는다.
const nuts = useBearStore((state) => state.nuts)
const honey = useBearStore((state) => state.honey)
이와 같이 store 전체가 아닌 필요한 state만 구독하는 것을 공식 문서에서 추천한다
또한 내부에 여러개의 상태 선택이 있는 객체를 구성하고싶을 때에,
useShallow 메서드를 사용해 해당 상태값을 비교해 값이 달라졌을때만 렌더링을 시킬 수 있다
import { create } from 'zustand'
import { useShallow } from 'zustand/react/shallow'
const useBearStore = create((set) => ({
nuts: 0,
honey: 0,
treats: {},
// ...
}))
// Object pick, re-renders the component when either state.nuts or state.honey change
const { nuts, honey } = useBearStore(
useShallow((state) => ({ nuts: state.nuts, honey: state.honey })),
)
// Array pick, re-renders the component when either state.nuts or state.honey change
const [nuts, honey] = useBearStore(
useShallow((state) => [state.nuts, state.honey]),
)
// Mapped picks, re-renders the component when state.treats changes in order, count or keys
const treats = useBearStore(useShallow((state) => Object.keys(state.treats)))
[불변성 유지]
불변성이 깨질 경우, react가 상태 변경 여부를 정확히 알 수 없게 되어서(기존 값 자체가 변경되기때문에)
불필요한 렌더링 발생 혹은 상태 변경이 반영되지 않는 문제가 발생할 수 있다
(깊이 중첩된 객체를 사용하는 경우의 불변성 유지 예시)
//이와 같은 깊은 객체를 가질 경우
type State = {
deep: {
nested: {
obj: { count: number }
}
}
}
1. ... 연산자를 사용해 기존 데이터를 건드리지 않고, 새로운 데이터 생성하기
normalInc: () =>
set((state) => ({
deep: {
...state.deep, //deep 객체 복사
nested: {
...state.deep.nested, //nested 객체 복사
obj: {
...state.deep.nested.obj, //obj 객체 복사
count: state.deep.nested.obj.count +1 //count 값만 변경
}
}
}
})),
=> 원본 state는 변하지 않고, 새로운 상태 객체 반환
2. immer 라이브러리 사용
immerInc: () =>
set(produce((state: State) => { ++state.deep.nested.obj.count })),
라이브러리를 사용해 더욱 간단하게 불변성을 유지할 수 있다
[immer() 메서드는
에서 제공하지만 produce 메서드를 사용하려면 immer 라이브러리를 설치해야하는것으로 보인다]
비동기 action
- 데이터 페칭 후 전역에 저장하고싶을 때 사용하면 될 듯 하다
const useFishStore = create((set) => ({
fishies: {},
fetch: async (pond) => {
const response = await fetch(pond)
set({ fishies: await response.json() })
},
}))
subscribe()
- 리렌더링 발생 없이 상태에 바인딩하기(with Ref)
- useEffect와 결합해, 언마운트시 구독이 해제되도록 할 것
const useScratchStore = create((set) => ({ scratches: 0, ... }))
const Component = () => {
// Fetch initial state
const scratchRef = useRef(useScratchStore.getState().scratches)
// Connect to the store on mount, disconnect on unmount, catch state-changes in a reference
useEffect(() => useScratchStore.subscribe(
state => (scratchRef.current = state.scratches)
), [])
...
storage를 사용한 미들웨어 지속
import { create } from 'zustand'
import { persist, createJSONStorage } from 'zustand/middleware'
const useFishStore = create(
persist(
(set, get) => ({
fishes: 0,
addAFish: () => set({ fishes: get().fishes + 1 }),
}),
{
name: 'food-storage', // name of the item in the storage (must be unique)
storage: createJSONStorage(() => sessionStorage), // (optional) by default, 'localStorage' is used
},
),
)
zustand/docs/integrations/persisting-store-data.md at main · pmndrs/zustand
🐻 Bear necessities for state management in React. Contribute to pmndrs/zustand development by creating an account on GitHub.
github.com
'today,weekly I learn' 카테고리의 다른 글
리액트 툴팁 토글링, 첫 방문시 아이콘 하이라이팅 (1) | 2024.12.02 |
---|---|
중요 요청 체이닝 (0) | 2024.11.26 |
IntersectionObserver api - 리액트, 무한스크롤 (0) | 2024.10.21 |
최종 프로젝트 간단한 리팩토링 (1) | 2024.10.16 |
리뷰 기능 수정 (2) | 2024.09.30 |