Redux Toolkit의 createSlice를 사용해 코드를 간소화시켜보자.
createSlice
createSlice
는 매개변수로 초기 state와 slice의 이름, reducer를 받아 reducer와 state에 해당하는 action type과 action 함수를 자동으로 생성해주는 함수이다. 즉, 리듀서와 액션을 따로 분리해서 작성할 필요 없이 하나의 함수로 간단하게 선언 및 관리할 수 있다는 것이다.
createSlice를 기존의 action, reducer 파일과 비교해 살펴보자.
action과 reducer
action과 reducer를 따로 선언했을 때의 코드는 아래와 같다. 보통 action 파일에는 액션 type 상수와 액션 함수를 선언해주고 reducer 파일에는 switch 문으로 각 액션에 해당하는 state를 업데이트하는 코드를 작성하는 것이 일반적이다.
/* action.js */
export const ADD_TODOS = 'todos/ADD_TODOS';
export const CHECK_TODOS = 'todos/CHECK_TODOS';
export const DELETE_TODOS = 'todos/DELETE_TODOS';
export const addTodos = (text) => {
return { type: ADD_TODOS, text };
};
export const checkTodos = (id) => {
return { type: CHECK_TODOS, id };
};
export const deleteTodos = (id) => {
return { type: DELETE_TODOS, id };
};
---
/* reducer.js */
import {
ADD_TODOS,
CHECK_TODOS,
DELETE_TODOS,
} from './action';
const initialState = {
todos: [],
};
export const todoReducer = (state = initialState.todos, action) => {
switch (action.type) {
case ADD_TODOS: {
return [
...state,
{
text: action.text,
completed: false,
},
];
}
case CHECK_TODOS: {
return [
...state.slice(0, action.id),
{ ...state[action.id], completed: !state[action.id].completed },
...state.slice(action.id + 1),
];
}
case DELETE_TODOS: {
return [...state.slice(0, action.id), ...state.slice(action.id + 1)];
}
default: {
return state;
}
}
};
세 개의 액션만 존재하는데도, 코드양이 길고 가독성이 떨어진다.
createSlice 사용
createSlice는 매개변수로 name
, initialState
, reducers
를 받는다. initialState
는 말 그대로 초기 state를 뜻하고 name
에 지정한 문자열은 액션 type 상수의 접두사로 사용된다.
reducers
의 key 값은 액션 type 상수를 생성할 때 name 접두사 뒤에 붙여지는 문자열이 되며, dispatch()에 불러와 사용할 수 있다. 즉, switch의 case 문과 같다고 할 수 있다.
위 action 파일과 reducer 파일에 작성된 코드를 합쳐 createSlice 함수로 선언하면 다음과 같다.
/* todosSlice.js */
import { createSlice } from '@reduxjs/toolkit';
const initialState = {
todos: [],
};
const todosSlice = createSlice({
name: 'todos',
initialState,
reducers: {
addTodos: (state, action) => {
state.todos.push({
text: action.payload,
completed: false,
});
},
checkTodos: (state, action) => {
const todo = state.todos[action.payload];
todo.completed = !todo.completed;
},
deleteTodos: (state, action) => {
state.todos = [
...state.todos.slice(0, action.payload),
...state.todos.slice(action.payload + 1),
];
},
},
});
export const { addTodos, checkTodos, deleteTodos } = todosSlice.actions;
export default todosSlice.reducer;
아까보다 훨씬 간결해진 코드를 볼 수 있다. 내보낸 todosSlice
는 store 파일에 불러와 사용한다.
import { configureStore } from '@reduxjs/toolkit';
import todosSlice from './components/todos/todosSlice';
const store = configureStore({
reducer: {
todosSlice,
},
});
export default store;
References