Redux의 단점
코드가 길다는 것입니다.
리덕스의 원리는
그림과 같이 Action -> Reducer -> store 의과정을 거칩니다.
하지만 이를 구현하기위해서 이전 포스팅에서와같이 많은 양의 코드가 필요했는데, redux toolkit은 이를 확연하게 줄여줍니다.
createAction
// export const ADD = "ADD";
// export const REMOVE = "REMOVE";
// export const AaddTodo = (text) => ({ type: ADD, text: text });
// export const AremoveTodo = (id) => ({ type: REMOVE, id: id });
import {createAction} from '@reduxjs/toolkit';
const addTodo = createAction("ADD");
const removeTod = createAction("REMOVE");
Reducer를 호출하는건 Action입니다.
Action을 구조화하기위해서 4줄의 코드를 2줄로 간소화 시킬수있습니다.
그리고 이 Action을 호출하면 인자로 payload가 항상함께담기고, 생성시에 인자로 넣은 string이 type으로 들어가게됩니다.
addTodo("새로운 doto 텍스트") // return {type:"ADD", payload:"새로운 doto 텍스트"}
createReducer
Reducer는 기존에는 switch문과 항상 mutate를 금지하여 새로운 state를 return 해주어야했습니다.
const initalState = [{ id: Date.now(), text: "go work" }];
// const todoReducer = (state = initalState, action) => {
// switch (action.type) {
// case addTodo:
// return [...state, { id: Date.now(), text: action.text }];
// case removeTod:
// return state.filter((todo) => todo.id !== action.id);
// default:
// return state;
// }
// };
const todoReducer = createReducer(initalState, {
[AaddTodo]: (state, action) => {
state.push({ id: Date.now(), text: action.payload });
},
[AremoveTodo]: (state, action) =>
state.filter((todo) => todo.id !== action.payload),
});
createReducer는 switch문 필요없이, 오브젝트형식으로 정의합니다. 첫번째 인자로는 초기 state값을 받습니다.
가장 중요한 점은 createReducer로 생성한 reducer는 state를 변경할때 mutate해도 된다는 점입니다.
코드를 자세히 보시면 filter같은 경우 새로운 객체를 반환합니다. 그리고 return 까지 해주고있죠
반면에 state.push를 하고있는 코드라인이 보입니다. state를 직접 수정한 것이죠, 그리고 이것은 어떤것도 return 하지 않습니다.
이는 redux toolkit이 불변성 유지를 대신 관리해주는 Immer이라는 라이브러리 아래에서 동작하기 때문입니다. 이로서 사용자의 실수를 줄여줄 수 있죠(개인적으로는 습관처럼 mutate하지 않도록 작성하는것이 좋은 습관이라고 생각합니다. 의존하는 라이브러리가 늘어난다는것은 좋지 않으니까요)
configureStore
리덕스 devtools를 사용하기위해서 createStore 대신 사용합니다.
추가적으로 미들웨어도 추가해줄수있습니다.
rootReducer.js
단순히 객체로 반환하도록 변경합니다.
import { combineReducers } from "redux";
import todoReducer from "./todoReducer";
import counterReducer from "./counterReducer";
const rootReducer = {
todoReducer,
counterReducer,
};
export default rootReducer;
index.js
import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import App from "./App";
import rootReducer from "./rootReducer";
import { Provider } from "react-redux";
import { configureStore } from "@reduxjs/toolkit";
const store = configureStore({ reducer: rootReducer });
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById("root")
);
createStore -> configureStore()로 변경하고 reducer프로퍼티에 reducer들을 추가해줍니다.
그러면 아래와같이 redux devtools 가 활성화되고, 직접 dispatch나, state 값 등을 모니터링 할수있습니다.
createSlice
위에서 createAction, createReducer 를 사용해서, 코드를 현저히 줄였습니다.
하지만 여전히 Action따로 Reducer따로 생성해주고있는데, 이 두가지를 한번에 생성하고 제공하도록 해주는 함수입니다.
todoReducer.js
import { createAction, createReducer, createSlice } from "@reduxjs/toolkit";
// export const AaddTodo = createAction("ADD");
// export const AremoveTodo = createAction("REMOVE");
const initialState = [{ id: Date.now(), text: "go work" }];
// const todoReducer = createReducer(initalState, {
// [AaddTodo]: (state, action) => {
// state.push({ id: Date.now(), text: action.payload });
// },
// [AremoveTodo]: (state, action) =>
// state.filter((todo) => todo.id !== action.payload),
// });
const todoReducer = createSlice({
name: "todoReducer",
initialState,
reducers: {
AaddTodo(state, action) {
state.push({ id: Date.now(), text: action.payload });
},
AremoveTodo(state, action) {
return state.filter((todo) => todo.id !== action.payload);
},
},
});
export const { AaddTodo, AremoveTodo } = todoReducer.actions;
export default todoReducer.reducer;
하나의 createSlice()에서 actions, reducers가 모두 생성되고있습니다.
하단의 export 구문이 바뀐점을 유의해 주세요
이렇게만 바꾼다면 다른 컴포넌트파일에서는 수정할 부분이 없습니다.
'Archive' 카테고리의 다른 글
Gatsby란? (0) | 2022.02.15 |
---|---|
[React 프로젝트] 썸네일 생성기 (0) | 2022.02.10 |
React에서 순수 Redux의 사용과 개념+원리 (0) | 2022.01.26 |
Vanilla Javascript Redux 사용해보기 와 핵심개념 (0) | 2022.01.26 |
React + Youtube API Youtube Clone 코딩 (0) | 2022.01.19 |