Zustand의 핵심 기능 + 설명을 담은 글
Zustand : 작고 빠르며 확장 가능한 React 프로젝트에서 사용하는 상태 관리 라이브러리
Flux ?
Flux는 Facebook에서 제안한 애플리케이션 아키텍처로 React와 함께 사용하기 위해 만들어졌다. Flux 방식의 핵심은 단방향 데이터 흐름(unidirectional data flow)를 따르는것이다.
-> 즉, 애플리케이션의 상태 관리를 간단하고 예측 가능하게 만든다.
zustand.docs 에 나와있는 예제 + TS(그냥 한번 해보고싶어서 내가 추가함)
create
함수의 제네릭으로 상태(State)와 액션(Action) 타입을 전달합니다. >>> create<GENERIC>()
interface BearStore {
// Init State
bears : number
// Actions
increasePopulation : () => void
removeAllBears : () => void
updateBears : (newBears: number) => void
}
import { create } from 'zustand'
const useStore = create<BearStore>((set) => ({
bears: 0,
increasePopulation: () => set((state) => ({ bears: state.bears + 1 })),
removeAllBears: () => set({ bears: 0 }),
updateBears: (newBears) => set({ bears: newBears }),
}))
create()
함수로 store를 생성한다. create()
함수의 콜백은 set
,get
매개변수를 가지며, 이를 통해 상태를 변경하거나 조회할 수 있다.create()
함수의 콜백이 반환하는 객체에서의 속성은 State
이고, 메소드는 Action
이다.import { create } from 'zustand'
export const useBearStore = create((set, get) => {
return {
const bears = get()//상태: 초깃값,
//액션: 함수
}
})
import React from "react";
import { create } from "zustand";
export const useBearStore = create((set, get) => {
return {
bears: 0,
food : 0 // << 이거 상태 업데이트 예제로 쓸 예정
increaseBear1: () => {
const state = get();
const { bears } = state;
set({ bears: bears + 1 });
},
};
});
const App = () => {
const bears = useBearStore((state) => state.bears);
const addBear = useBearStore((state) => state.increaseBear1);
const increaseBear = useBearStore((state) => state.increaseBear2);
const logState = () => {
const state = useBearStore.getState();
console.log("Full state:", state);
};
return (
<>
<h1>{bears} around here...</h1>
<button onClick={addBear}> + 1</button>
<button onClick={increaseBear}> + 1</button>
<button onClick={logState}>Log Full State</button>
</>
);
};
export default App;
// Food 컴포넌트
const Food = () => {
const food = useBearStore((state) => state.food);
console.log("Food rendered:", food);
return <h1>Food: {food}</h1>;
};
// App 컴포넌트
const App = () => {
// 객체 분해로 꺼내옴, Food는 사용 X 하지만 Food 재렌더링 발생
const { bears, food } = useBearStore();
const increaseBear = useBearStore((state) => state.increaseBear2);
return (
<>
<Food />
<h1>{bears} bears around here...</h1>
<button onClick={increaseBear}> + 1 Bear</button>
</>
);
};
export default App;
.getState()
를 사용하면 상태에대한 구독을 하지 않는다.const App = () => {
const { bears } = useBearStore.getState();
const increaseBear = useBearStore((state) => state.increaseBear2);
return (
<>
<Food />
<h1>{bears} bears around here...</h1>
<button onClick={increaseBear}> + 1 Bear</button>
</>
);
};
export default App;
get
함수를 호출하면, 상태와 액션이 포함된 스토어 객체를 얻을 수 있다.
이를 통해, 각 액션에서 상태의 값을 얻을 수 있음
import { create } from 'zustand'
export const useCountStore = create<{
count: number
increase: () => void
decrease: () => void
}>((set, get) => ({
count: 1,
increase: () => {
const { count } = get()
set({ count: count + 1 })
},
decrease: () => {
const { count } = get()
set({ count: count - 1 })
}
}))
get
함수를 사용하지 않고 set
함수의 콜백을 사용하면 더 간결하게 상태 변경 가능
import { create } from 'zustand'
export const useCountStore = create<{
count: number
increase: () => void
decrease: () => void
}>(set => ({
count: 1,
increase: () => set(state => ({ count: state.count + 1 })),
decrease: () => set(state => ({ count: state.count - 1 }))
}))
여러 컴포넌트에서 단일 스토어의 액션을 많이 사용한다면, 액션을 분리해 관리하는 패턴을 활용할 것
import { create } from 'zustand'
export const useCountStore = create(set => ({
count: 1,
actions: {
increase: () => set(state => ({ count: state.count + 1 })),
decrease: () => set(state => ({ count: state.count - 1 }))
}
}))
아래는 ts로 작성한 코드
import { create } from 'zustand'
export const useCountStore = create<{
count: number
actions: {
increase: () => void
decrease: () => void
}
}>(set => ({
count: 1,
actions: {
increase: () => set(state => ({ count: state.count + 1 })),
decrease: () => set(state => ({ count: state.count - 1 }))
}
}))
import { useCountStore } from './store/count'
export default function App() {
const count = useCountStore(state => state.count)
const { increase, decrease } = useCountStore(state => state.actions)
return (
<>
<h2>{count}</h2>
<button onClick={increase}>+1</button>
<button onClick={decrease}>-1</button>
</>
)
}
여기까지 Zustand 기본 사용방법이다.
확실히 Zustand는 편하다.