리덕스(redux-toolkit)

Gunwoo Kim·2021년 10월 8일
0

React

목록 보기
20/21
post-thumbnail
post-custom-banner

Redux-Toolkit?

앞서 리덕스 사용 방법에 대해서 공부해봤습니다.
그렇다면Redux Toolkit은 무엇일까요?
리덕스 툴킷도 리덕스입니다. 그렇다면 리덕스 툴킷은 왜 나오게 된걸까요?
현재 리덕스 공식문서에서도 기본적으로 리덕스 툴킷을 추천하고 있습니다.

리덕스 공식문서에는 아래와 같이 소개하고 있습니다.

'Redux Toolkit은 Redux 로직을 작성하기 위해 저희가 공식적으로 추천하는 방법입니다. RTK는 Redux 앱을 만들기에 필수적으로 여기는 패키지와 함수들을 포함합니다. 대부분의 Redux 작업을 단순화하고, 흔한 실수를 방지하며, Redux 앱을 만들기 쉽게 해주는 모범 사례를 통해 만들어졌습니다.'
- 리덕스 공식문서

결국 리덕스 툴킷은 기존 리덕스를 조금 더 쉽게 안정적으로 만들어지기 위해 나온것으로 보입니다.

리덕스 툴킷 사용하기

이번에는 리덕스 툴킷을 통해 기존 리덕스를 변경해보도록 하겠습니다.

라이브러리 다운로드

리덕스 툴킷을 설치하게 되면 기본적으로 redux-devtools-extension로 라이브러리가 설치되어 따로 설치할 필요가 없습니다.

// 리덕스 라이브러리 다운로드
$ npm install @reduxjs/toolkit react-redux

1. App 에 적용하기

기존 리덕스에서 사용하던 방법과 동일합니다.

import React from "react";
import ReactDOM from "react-dom";
import { Provider } from "react-redux";
import App from "App";
import store from "app/store";

ReactDOM.render(
  <React.StrictMode>
    <Provider store={store}>
      <App />
    </Provider>
  </React.StrictMode>,
  document.getElementById("root")
);

2. app/store 파일 configureStore 적용하기

리덕스 툴킷에서는 app폴더를 안에 store.js 파일을 통해 하나의 스토어 정의를 하도록 하고 각각의 features폴더 아래에 리덕스가 사용되는 컴포넌트와 --slice.js파일을 통해 리덕스 상태를 관리하고 있습니다.

기존에 createStore에서 configureStore로 변경이 되었으며 객체 형태의 인자에는 reducer가 필수로 존재해야합니다.

// app/store.js
import { configureStore } from "@reduxjs/toolkit";
import todoSlice from "features/todo/todoSlice";

export const store = configureStore({
  reducer: {
    todo: todoSlice,
  },
});

3. features 폴더에 Slice 생성하기

리덕스 툴킷에는 createAction, createReducer 등 다양한 API를 제공하고 있지만 저는 createSlice를 사용하도록 하겠습니다.

slice는 리듀서와 action creator 등의 기능들을 제공해주는 객체입니다.

slice를 사용하게 될 경우 기존의 inital state 와 액션, 리듀서를 하나로 통합하여 만들수 있으며 리덕스 툴킷에는 기본적으로 immer 라는 라이브러리가 내장되어있어 기존에 불변성을 위해 사용되는 concat, map, filter 등을 사용하여 불변성을 관리할 필요없이 알아서 관리를 해주기 때문에 아래와 같이 상태를 직접 변경해도 됩니다.

// features/todo/todoSlice.js
import { createSlice } from "@reduxjs/toolkit";

const INITIAL_STATE = {
  todos: [{ id: 1, text: "첫번째", done: false }],
};

export const slice = createSlice({
  name: "todo",
  initialState: INITIAL_STATE,
  reducers: {
    todoInsert: (state, action) => {
      const insertId =
        Math.max(0, ...state.todos.map((todo) => Number(todo.id))) + 1;
      const insertText = action.payload;
      state.todos.push({ id: insertId, text: insertText, done: false });
    },
    todoRemove: (state, action) => {
      const deleteId = action.payload;
      const index = state.todos.findIndex((todo) => todo.id === deleteId);
      state.todos.splice(index, 1);
    },
    todoUpdate: (state, action) => {
      const { id: updateId, text: updateText } = action.payload;
      const index = state.todos.findIndex((todo) => todo.id === updateId);
      state.todos[index].text = updateText;
    },
    todoToggle: (state, action) => {
      const toggleId = action.payload;
      const index = state.todos.findIndex((todo) => todo.id === toggleId);
      state.todos[index].done = !state.todos[index].done;
    },
  },
});

export const { todoInsert, todoRemove, todoUpdate, todoToggle } = slice.actions;

export const selectTodo = (state) => state.todo;
export const selectTodos = (state) => state.todo.todos;

export default slice.reducer;

4. 컴포넌트에서 사용하기

기존 사용과 마찬가지로 useSelector, useDispatch 를 통해 상태를 변경 할 수 있습니다.

2, 3과 같이 slice에서 따로 상태를 정의하여 useSelect를 통해 사용할 수 있습니다.

import { useSelector, useDispatch } from "react-redux";
import { todoInsert } from "./todoSlice";
import { selectTodo, selectTodos } from "./todoSlice";

export default function Components() {
  1. const { todos } = useSelector((state) => state.todo);
  2. const { todos } = useSelector(selectTodo);
  3. const todos = useSelector(selectTodos);
  const dispatch = useDispatch();

  const handleDispatch = () => {
    dispatch(todoInsert({ payload }));
  };
}

리덕스 공식문서(리덕스 툴킷)
https://ko.redux.js.org/redux-toolkit/overview
리덕스 툴킷 공식문서
https://redux-toolkit.js.org
화해 블로그 리덕스 툴킷 http://blog.hwahae.co.kr/all/tech/tech-tech/6946
👉 깃주소
https://github.com/kim-gunwoo/redux-exam

post-custom-banner

0개의 댓글