실전프로젝트에서 우리 리액트 팀원 3명은
상태관리를 리덕스 툴킷으로 하기로 했다
설치
yarn add redux react-redux @reduxjs/toolkit
createStore로 store를 생성하고, configureStore로 간단하게 store 세팅을 할 수 있는데, reducer 필드는 필수적으로 전달해야 하며, 추가적으로 middleware 등을 추가해 줄 수 있다. 기존처럼 combineReducers로 reducer들을 결합하지 않아도 자동적으로 reducer들을 결합해 주며, redux-thunk 미들웨어를 디폴트로 포함하고 있다.
import { configureStore } from '@reduxjs/toolkit';
import { useDispatch } from 'react-redux';
export const store = configureStore({
reducer: {},
});
export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;
export const useAppDispatch = () => useDispatch<AppDispatch>();
공식 문서에 따르면 리덕스 앱은 상태트리 최상단에 combineReducersjs 함수로 결합한 root reducer 객체를 가지고 있는데, 이 객체에서 각각의 key/value 쌍을 slice라고 하며, 해당 slice를 업데이트 하는 reducer 함수를 slice reducer라고 한다.
Redux Toolkit에서는 createSlice API로 action과 reducer를 간단하게 생성할 수 있다. 큰 장점 중 하나로 immer의 produce를 자체적으로 지원해 주기 때문에 state를 직접 변형(mutate) 할 수 있다.
import { createSlice } from '@reduxjs/toolkit'
const todosSlice = createSlice({
// 액션 타입 문자열의 prefix로 사용됨
name: 'todos',
// 초기 state 값
initialState: [],
// 리듀서 맵. key는 액션 타입 문자열이 되고(ex. todos/addTodo), 함수는 액션이 dispatch 될 때 실행되는 reducer
reducers: {
addTodo(state, action) {
const { id, text } = action.payload
state.push({ id, text, completed: false })
},
toggleTodo(state, action) {
const todo = state.find(todo => todo.id === action.payload)
if (todo) {
todo.completed = !todo.completed
}
}
}
})
const { actions, reducer } = todosSlice;
export const { addTodo, toggleTodo } = actions;
export default reducer