[React] Redux-toolkit

J·2023년 5월 13일
0

React

목록 보기
16/25
post-thumbnail
  • 리덕스 툴킷이란?

  • 리덕스를 사용하기 위해 작성했던 ducks 패턴의 요소들이 전체적인 코드량을 늘린다는 불편함에 등장함.

  • 리덕스를 더 편하게 쓰기 위한 기능들을 흡수하고 코드량은 적게 만듦. 그러나 새로운 것은 아님. 리덕스 구조나 패러다임은 동일. 바뀐 부분은 모듈 파일 뿐임.

  • 설치

    yarn add react-redux @reduxjs/toolkit
  • 기존 리덕스 코드와 비교
    • 일반 리덕스 - count
      // 일반 리덕스 예시 코드
      
      // Action Value
      const ADD_NUMBER = "ADD_NUMBER";
      const MINUS_NUMBER = "MINUS_NUMBER";
      
      // Action Creator
      export const addNumber = (payload) => {
        return {
          type: ADD_NUMBER,
          payload,
        };
      };
      
      export const minusNumber = (payload) => {
        return {
          type: MINUS_NUMBER,
          payload,
        };
      };
      
      // Initial State
      const initialState = {
        number: 0,
      };
      
      // Reducer
      const counter = (state = initialState, action) => {
        switch (action.type) {
          case ADD_NUMBER:
            return {
              number: state.number + action.payload,
            };
          // [퀴즈 답]
          case MINUS_NUMBER:
            return {
              number: state.number - action.payload,
            };
          default:
            return state;
        }
      };
      
      // export default reducer
      export default counter;
    • 툴킷
      // src/redux/modules/counterSlice.js
      
      import { createSlice } from "@reduxjs/toolkit";
      
      const initialState = {
        number: 0,
      };
      
      const counterSlice = createSlice({
        name: "counter",
        initialState,
        reducers: {
          addNumber: (state, action) => {
            state.number = state.number + action.payload;
          },
      
          minusNumber: (state, action) => {
            state.number = state.number - action.payload;
          },
        },
      });
      
      // 액션크리에이터는 컴포넌트에서 사용하기 위해 export 하고
      export const { addNumber, minusNumber } = counterSlice.actions;
      // reducer 는 configStore에 등록하기 위해 export default 합니다.
      export default counterSlice.reducer;
      • 큰 차이점은 Action Value와 Action Creator를 직접 생성해주지 않고 Action Value, Action Creator, Reducer가 하나로 합쳐짐.
        //createSlice API 뼈대
        
        const counterSlice = createSlice({
        	name: '', // 이 모듈의 이름
        	initialState : {}, // 이 모듈의 초기상태 값
        	reducers : {}, // 이 모듈의 Reducer 로직
        })
      • Slice 라는 툴킷 API 사용. counterSlice 리듀서 객체 안에서 만들어주는 함수가 리듀서의 로직이 되면서 동시에 Action Creator가 됨. Action Value까지 함수의 이름을 따서 자동으로 만들어짐. 그래서 Reducer만 만들어주면 됨.
        // counterSlice.js의 Slice 구조
        
        const counterSlice = createSlice({
          name: "counter",
          initialState,
          reducers: {
            // 리듀서 안에서 만든 함수 자체가 리듀서의 로직이자, 액션크리에이터가 된다.
            addNumber: (state, action) => {
              state.number = state.number + action.payload;
            },
        
            minusNumber: (state, action) => {
              state.number = state.number - action.payload;
            },
          },
        });
      • 일반 리덕스에서 export를 통해서 각각 Action Creator를 내보내주었던 것을 똑같이 내보낼 수 있음. 리듀서에 로직을 추가할 때마다 함수를 추가해서 내보내주면 됨.
        // 액션크리에이터는 컴포넌트에서 사용하기 위해 export 하고
        export const { addNumber, minusNumber } = counterSlice.actions;
        // reducer 는 configStore에 등록하기 위해 export default 합니다.
        export default counterSlice.reducer;
  • configStore 비교
    • 일반 리덕스 -count
      // 일반 리덕스 combineReducers 예시 코드
      
      import { createStore } from "redux";
      import { combineReducers } from "redux";
      import counter from "../modules/counter";
      
      const rootReducer = combineReducers({
        counter,
      });
      const store = createStore(rootReducer);
      export default store;
    • 툴킷
      // src/redux/modules/config/configStore.js
      
      import { configureStore } from "@reduxjs/toolkit";
      /**
       * import 해온 것은 slice.reducer 입니다.
       */
      import counter from "../modules/counterSlice";
      import todos from "../modules/todosSlice";
      
      /**
       * 모듈(Slice)이 여러개인 경우
       * 추가할때마다 reducer 안에 각 모듈의 slice.reducer를 추가해줘야 합니다.
       *
       * 아래 예시는 하나의 프로젝트 안에서 counter 기능과 todos 기능이 모두 있고,
       * 이것을 각각 모듈로 구현한 다음에 아래 코드로 2개의 모듈을 스토어에 연결해준 것 입니다.
       */
      const store = configureStore({
        reducer: { counter: counter, todos: todos },
      });
      
      export default store;
    • 이렇게 생성한 store를 export default해서 최상위 index.js Provider에 주입해주는 것은 바뀐게 없음. App.jsx에서도 툴깃을 사용해서 만든 모듈을 조회할 수 있고 방법을 동일함.
      // index.js
      
      import React from "react";
      import ReactDOM from "react-dom/client";
      import App from "./App";
      import { Provider } from "react-redux";
      import store from "./redux/config/configStore";
      
      const root = ReactDOM.createRoot(document.getElementById("root"));
      root.render(
        <Provider store={store}>
          <App />
        </Provider>
      );
      // src/App.js
      
      import React from "react";
      import { useSelector } from "react-redux";
      
      const App = () => {
        // Store에 있는 todos 모듈 state 조회하기
        const todos = useSelector((state) => state.todos);
      
        // Store에 있는 counter 모듈 state 조회하기
        const counter = useSelector((state) => state.counter);
      
        return <div>App</div>;
      };
      
      export default App;
  • Redux Devtools
    • 현재 프로젝트의 state 상태나 어떤 액션이 일어났을 때 그 액션이 무엇이고 그것으로 인해 state가 어떻게 변경되었는지 등 개발할 때 편리하게 사용할 수 있는 tool.
    • 프로젝트가 복잡해질수록 이 툴을 이용해서 쉽게 디버깅 가능함.
    • 툴킷이 아닌 일반 리덕스에서 devtools를 사용하고자 한다면 별도의 설정이 필요함. 툴킷은 devtool이 내장되어 있기 때문에 별도 코드 설정 없이 사용 가능함. 또한 thunk, immer 등의 주요 패키지 등도 내장되어 있음.
  • 정리
    • slice API를 이용하면 Reducer, Action Value, Action Creator를 한 번에 구현할 수 있음.
    • 툴킷을 사용하면 별도 설정 없이 devtools 사용 가능.
profile
벨로그로 이사 중

0개의 댓글