Redux Toolkit

Jtiiin:K·2023년 11월 28일
1
post-thumbnail

< Redux Toolkit >

✅ 리덕스 툴킷이란?

  • 리덕스를 개량한 것(새로운 것 X)
  • 리덕스를 사용하기 위해 작성했던 ducks 패턴의 요소들이 전체 코드양을 늘린다는 개발자들의 불만이 생기기 시작했고, 리덕스팀에서는 이를 수용, 코드를 더 적게, 그리고 리덕스를 더 편하게 쓰기 위한 기능들을 흡수해서 만든 것
  • 안에 immer 기능이 내장되어 있어서 불변성도 지켜줌 🐶🍯

✅ 툴킷 설치

yarn add react-redux @reduxjs/toolkit

✅ 일반 리덕스와 비교

🔽 일반 리덕스 🔽


// 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: { // 모듈의 Reducer 로직 + Action Creator + Action Value 역할
    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;

slice API 사용

👉 action value와 Action Create를 직접 생성해주지 않음
(action value + Action Create + Reducer 가 하나로 합쳐짐)
👉 reducers 에 's' 빼먹지 말기!


✅ ConfigStore 비교

🔽 일반 리덕스 🔽

import { createStore } from "redux";
import { combineReducers } from "redux";
import counter from "../modules/counter";

const rootReducer = combineReducers({
  counter,
});
const store = createStore(rootReducer);
export default store;

🔽 리덕스 툴킷 🔽

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;

🔽 Provider 적용은 동일 🔽

// 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>
);

🔽 모듈 조회방식도 동일 🔽

  • useSelector 사용
// 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가 어떻게 변경되었는지 등을 확인할 수 있음
  • 일반 리덕스에서 사용할 때는 별도 설정이 필요하지만 툴킷은 내장되어 있으므로 별도 설정 필요 없이 바로 사용 가능
profile
호기심 많은 귀차니즘의 공부 일기

0개의 댓글