이 전에 작성 된 글을 이어서 이번엔 Redux Toolkit
을 사용하여 코드를 다듬어보려고 합니다.
먼저 RTK
라고도 불리는 Redux Toolkit
에 대해 간략하게 알아보고 바로 코드를 수정해보겠습니다!
이 글은 노마드코더의 Redux 강의를 보고 학습하며 다시 정리한 내용입니다.
Redux Toolkit은 Redux 구성 작업을 단순화하고, 실수를 방지하며, 쉽게 사용할 수 있도록 하기위해 만들어진 도구입니다. Redux에 대해 우려하는 세 가지를 해결하기 위해 만들어졌다고 합니다.
이러한 문제를 해결하기 위해 만든 RTK는 Redux에서 강력하게 권장한다고 합니다. 이 도구로 인해 코드를 더 좋게 유지보수하기 쉽게 만들어준다고 하네요.
yarn add @reduxjs/toolkit
//or
npm install @reduxjs/toolkit
그럼 이전에 작성했던 redux 문법들을 다음과 같이 RTK 문법으로 수정해보도록 하겠습니다.
createStore
-> configureStore()
reducer
-> createReducer()
actionFunction
-> createAction()
마지막에는 리듀서 함수와 액션 생성자와 타입을 모두 포함하는 으마무시한 createSlice()
함수로 리팩토링을 진행해보도록 하겠습니다.
import { createAction } from "@reduxjs/toolkit";
export const addToDo = createAction("ADD");
export const deleteToDo = createAction("DELETE");
먼저 액션 생성 함수를 이렇게 간단하게 1줄로 표현해줄 수 있게 되었습니다. 이전 코드와 비교해보면 훨씬 간결해진 것을 알 수 있습니다. createAction(action.type)
함수 괄호 안에는 type
으로 사용할 매개변수만 전달하면 됩니다.
이제 store
를 리팩토링하면서 action
을 어떻게 받아서 처리하는지 확인해보도록 하겠습니다.
import { createReducer, configureStore } from "@reduxjs/toolkit";
import { addToDo, deleteToDo } from "../action";
// createReducer();
const toDoReducer = createReducer([], {
[addToDo]: (state, action) => {
state.push({ text : action.payload, id : Date.now() });
},
[deleteToDo]: (state, action) =>
state.filter((toDo) => toDo.id !== action.payload);
});
export const store = configureStore({ reducer : toDoReducer })
store
의 리팩토링을 하였습니다. 달라진 부분이 보이시나요?
어떤 부분이 리팩토링 되었을까요?
createReducer(초기값, { 리듀서 역할 수행 })
사용- switch 문 ->
createAction
변수 사용 =[addToDo]
action.payload
- payload는
createAction()
을 사용하게 되면action.type
외의 값은 모두 payload에 담기게 됩니다. (action.text === action.payload)- action.payload는 리덕스의 관습이라고 보면 되겠습니다.
- createStore() -> configureStore()로 변경
그리고 마지막으로 가장 중요한 부분이 하나 있습니다. 바로 state.push
를 사용한 점 입니다. RTK에서는 이러한 문법이 허용되는데 다만 mutate
메서드를 사용할 땐 return
을 하지 않아야 합니다. 리듀서 내부의 [addToDo]
, [deleteToDo]
부분을 비교해보겠습니다.
// 괄호 안에서 Array.push 후에 return을 하지 않음.
[addToDo] : (state, action) => {
state.push({ text : action.payload, id : Date.now() });
};
// Array.filter는 새로운 배열을 반환하기에 바로 return 되어도 문제가 없음
[deleteToDo]: (state, action) =>
state.filter((toDo) => toDo.id !== action.payload);
어떤 차이를 가졌는지 이해가 되셨나요? RTK에서는 createReducer
, createSlice
에서 업데이트 로직을 대폭 단순화하기 위해 내부적으로 immer
를 사용하여 상태가 업데이트 되기 때문에 mutate
메서드를 사용할 수 있다고 합니다.
개발자가 신경써야하는 부분이 적어져서 좀 더 편리하게 사용할 수 있을 것 같습니다.
이제 마지막으로 createSlice()
을 사용하여 리팩토링을 진행해보겠습니다.
import { createSlice } from "@reduxjs/toolkit";
const toDos = createSlice({
name : "toDoReducer",
initialState: [],
reducers: {
add: (state, action) => {
state.push({ text : action.payload, id : Date.now() });
},
remove: (state, action) =>
state.filter((toDo) => toDo.id !== action.payload);
},
});
// dispatch 액션 발생을 위한 액션 생성자를 export하여 외부에서 사용
export const { add, remove } = toDos.actions;
export default configureStore({ reducer: toDos.reducer });
createSlice()
를 사용하면 위의 코드와 같이 액션 생성자와 타입이 합쳐져있고, 리듀서의 역할 수행도 함수 안에 포함되어 있습니다. 이렇게 작성하면 따로 액션 생성 함수를 만들거나 타입을 지정할 필요가 없습니다.
이제 마지막으로 <Home />
, <ToDo />
두 컴포넌트를 수정하겠습니다.
import { useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import ToDo from "../components/ToDo";
import { add } from "../store";
function Home() {
const [text, setText] = useState("");
const toDos = useSelector((state) => state);
const dispatch = useDispatch();
function onChange(e) {
setText(e.target.value);
}
function onSubmit(e) {
e.preventDefault();
dispatch(add(text));
setText("");
}
return (
<>
<h1>To Do</h1>
<form onSubmit={onSubmit}>
<input
type="text"
placeholder="What To Do?"
value={text}
onChange={onChange}
/>
<button>Add</button>
</form>
<ul>
{toDos.map((todo) => (
<ToDo {...todo} key={todo.id} />
))}
</ul>
</>
);
}
export default Home;
import { useDispatch } from "react-redux";
import { remove } from "../store";
function ToDo({ text, id }) {
const dispatch = useDispatch();
return (
<li>
{text}
<button onClick={() => dispatch(remove(id))}>Del</button>
</li>
);
}
export default ToDo;
Redux Toolkit을 사용하여 리팩토링을 완료하였습니다. 이전에 작성 한 코드와 리팩토링 된 코드를 비교해보시면 놀라울정도로 코드가 깔끔하고 간결해졌습니다. 왜 리덕스에서 RTK를 강력하게 권장하는지 체감을 할 정도입니다. Redux와 Redux Toolkit에는 아직 소개해드리지 못한 함수나 기능들이 있습니다. 이 부분들은 제가 좀 더 학습을하고나서 글을 작성하도록 하겠습니다.
그럼 두서 없는 이 글을 끝까지 읽어주셔서 감사합니다.
.
.
.
.
.
참고사이트
Redux Toolkit - 공식 문서