https://www.heropy.dev/p/n74Tgc
/src/store/countSlice.ts
interface CountState {
count: number
double: nubmer
}
const initialState: CountState = {
count: 0,
double: 0
}
export const countSlice = createSlice({
name: 'count',
initialState,
reducers: {
increase: state => {
state.count += 1
state.couble = state.count * 2
},
decrease: state => {
state.count -= 1
state.double = state.count * 2
}
}
})
export const { increase, decrease } = countSlice.actions
export default countSlice.reducer
/src/store/index.ts
import countReducer from './countSlice'
export const store = configureStore({
reducer: {
count: countReducer
}
})
export type RootState = ReturnType<typeof store.getState>
export type AppDispatch = typeof store.dispatch
/src/main.tsx
createRoot(document.getElementById('root')!).render(
<Provider store={store}>
<App />
</Provider>
)
/src/App.tsx
export default function App(){
const { count, double } = useSelector((state:RootState) => state.count)
const dispatch = useDispatch()
return (
<>
<h2>Count: {count}</h2>
<h2>Double: {double}</h2>
<button onClick={() => dispatch(increase())}>+1</button>
<button onClick={() => dispatch(decrease())}>-1</button>
</>
)
}
상태(state)를 관리하는 React Hook입니다.
const [state, dispatch] = useReducer(reducer, initialState);
상태를 직접 변경하지 않고 "무슨 일이 일어났는지"를 reducer에게 알리는 역할
dispatch({
type: "INCREASE"
});
dispatch가 전달한 액션을 받아 새로운 state를 반환합니다.
function reducer(state, action) {
switch (action.type) {
case "INCREASE":
return {
count: state.count + 1
};
default:
return state;
}
}
dispatch(action)
↓
reducer
↓
새로운 state 생성
↓
화면 렌더링
| 비교 | Redux | Zustand | 선택 이유 |
|---|---|---|---|
| Store 정의 | createSlice 및 configureStore 분리 | create 함수 하나로 통합 | 보일러플레이트 코드 대폭 감소 |
| 액션/리듀서 | reducers 객체 내 정의. 액션은 별도 export 필요 | set 함수를 사용하는 일반 함수로 정의 | 액션과 리듀서의 경계가 사라져 직관적 |
| 파일 구조 | Slice 파일, Store 설정 파일 등 다수 | Store 정의 파일 하나로 충분 | 프로젝트 구조가 단순하고 관리가 용이 |
| 불변성 관리 | Immer를 통한 간접적인 강제 | set 함수 내에서 직접 불변성 처리 가능 | 코드 작성 시 상태 흐름이 명확함 |
| Provider | 필수 (Context 기반) | 불필요 (클로저 기반) | 애플리케이션 최상위 구조가 단순해짐 |
| 선택적 구독 | useSelector 내에서 구현 필요 | 훅 사용 시 기본적으로 부분 상태만 구독 | 불필요한 리렌더링 방지 및 성능 최적화 용이 |
| 비동기 처리 | createAsyncThunk 또는 Redux-Sage/Thunk 미들웨어 | set 함수 내에서 간다히 처리. 미들웨어로 확장 가능 | 복잡한 설정 없이 비동기 로직 구현 가능 |
/src/store/countStore.ts
export const useCountStore = create (
combine (
{
count: 0,
double: 0
},
set => ({
increase: () =>
set(state => ({
count: state.count + 1,
double: (state.count + 1) * 2
})),
decrease: () =>
set(state => ({
count: state.count -1,
double: (state.count -1) * 2
}))
})
)
)
/src/App.tsx
export default function App() {
const count = useCountStore(state => state.count)
const double = useCountStore(state => state.double)
const increase = useCountstore(state => state.increase)
const decrease = useCountStore(state => state.decrease)
return (
<>
<h2>Count: {count}</h2>
<h2>Double: {double}</h2>
<button onClick={increase}>+1</button>
<button onClick={decrease}>-1</button>
</>
)
}