항해/TIL

TIL(2/26) / Redux Toolkit(Feat.Flux Pattern)

yeeendy 2024. 2. 26. 21:06

기존의 redux는 ducks패턴에 맞춰 코드를 작성하다보니 전체적인 코드의 양이 늘어 가독성이 떨어지는 등 불편함이 커졌다.

그래서 리덕스 팀에서 코드는 더 적게, 더 편하게 리덕스를 사용하기 위해 리덕스툴킷(RTK)을 만들었다.

사용방식은 기존과 동일하고 액션 세팅, 스토어 등 모듈 파일 부분만 좀 다르다.

 

리덕스툴킷(RTK) 설치방법

툴킷 사용을 위해 react-redux도 꼭 같이 설치해주어야 한다.

yarn add react-redux @reduxjs/toolkit
npm install react-redux @reduxjs/toolkit

 

 

예시로 보는 redux와 redux-toolkit의 코드 차이

<<redux>>

// 일반 리덕스 예시 코드

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

 

<<redux toolkit>>

// 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를 직접 생성하지 않고

createSlice를 import해서 Action Value, Action Creator, Reducer를 한 번에 작성할 수 있다.

=> 리듀서의 로직이 되면서 동시에 Action Creator가 된다!

 

createSlice

const counterSlice = createSlice({
	name: '', // 이 모듈의 이름
    initialstate: {}, // 이 모듈의 초기상태 값
    reducers: {}, // 이 모듈의 Reducer 로직
})

 

configStore의 차이

<<redux>>

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

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

 

<<redux toolkit>>

import { configureStore } from "@reduxjs/toolkit";

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;

 

차이점

리덕스 툴킷은 createStore, combineReducers 를 import할 필요없이 configureStore만 import해오면 된다.

 

FLUX 패턴

단방향 데이터 흐름

아래와 같은 흐름으로 흘러간다는 것을 기억하자

Action → Dispatch → Reducer → Store

(   함수   →    객체    →    함수    →   저장소   )

  1. 상태가 변경되어야 하는 이벤트가 발생하면, 변경될 상태에 대한 정보가 담긴 Action 객체가 생성됩니다.
  2. 이 Action 객체는 Dispatch 함수의 인자로 전달됩니다.
  3. Dispatch 함수는 Action 객체를 Reducer 함수로 전달해 줍니다.
  4. Reducer 함수는 Action 객체의 값을 확인하고, 그 값에 따라 전역 상태 저장소 Store의 상태를 변경합니다.
  5. 상태가 변경되면, React는 화면을 다시 렌더링 합니다.