우주먼지 개발 log

[react] Redux Toolkit 사용하기 (일반리덕스를 redux toolkit으로 리팩토링) 본문

react

[react] Redux Toolkit 사용하기 (일반리덕스를 redux toolkit으로 리팩토링)

개발자먼지 2023. 11. 29. 14:08
반응형

redux Toolkit

redux를 개량하여 코드를 더 적게, 편하게 사용할 수 있게 해주는 툴킷이다.

ducks 패턴의 자동화! (ducks 패턴, 나중 정리)

 

일반 리덕스 사용하는 법 다시보기

폴더 구조와, Provider 주입해주는 부분은 동일하기 때문에 이번엔 Pass !

 

[TIL] 23/11/09 React 숙련: Redux 란?

한 일 - redux 강의 다 듣기 - 알고리즘 스터디 : 프로그래머스 4문제 풀기 TIL Redux ? 전역 상태(Global state) 관리 라이브러리 기존 useState 불편 해소 - 컴포넌트 간에 상태(state)를 공유 하려면 부모자식

developer.happymunzi.com

 

redux Toolkit설치

프로젝트 생성 후 yarn 을 이용해 패키지 설치하기 react-redux와 툴킷을 설치 (난 npm은 모른다)

yarn add react-redux @reduxjs/toolkit

 

일반 redux를 redux toolkit으로 리팩토링

 

redux Toolkit 사용하여 일반 redux를 리팩토링

1. 일반 리덕스는 3가지를 설정해야 했다!

- 문자열 오탈자 방지를 위한 action value

- action 객체를 리턴해주는 action creator

- action 마다 state를 어떻게 변경해 줄 것인지를 설정하는 reducer 

// 일반 리덕스 예시 코드
//redux/modules/counter.js

// Action Value
const ADD_NUMBER = "ADD_NUMBER";

// Action Creator
export const addNumber = (payload) => {
  return {
    type: ADD_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,
      };
    default:
      return state;
  }
};

// export default reducer
export default counter;

 

2. redux toolkit으로 3가지를 한번에!

- slice API를 통해 action value와 action creator와 reducer를 한번에 만들어준다.

// 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; // state 객체의 number 를 직접바꿔도 ok
    },
  },
});

// 액션크리에이터는 컴포넌트에서 사용하기 위해 export 하고
export const { addNumber, minusNumber } = counterSlice.actions;

// reducer 는 configStore에 등록하기 위해 export default 합니다.
export default counterSlice.reducer;

 


 

자세히 보기

더보기

slice API

createSlice 를 통해 slice 만들기
- createSlice 함수는 아래 3가지를 객체로 묶어 인자로 받는다.

- name, initialState, reduces

//createSlice API 뼈대

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

 

 

reducers

reducers 안에 리듀서를 추가하기

 - reducers: { key : 함수,  }  이런식으로 추가해주면 자동으로 action value와 action creator를 생성해준다.

 - 위에서는 코드가 길어서 생략했는데 minusNumber 라는 리듀서를 추가해 보았다.

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

 

* 참고 : 원래 redux에서는 불변성 유지를 신경 써줘야했는데..  
redux toolkit 에서는 immer라는 기능을 내장하고 있어서

reducer 내에 불변성을 해치는 코드를 작성하더라도 알아서 고쳐준다.

위 counter 코드에서도 state의 number 값을 직접 수정한 것도!

// 불변성을 유지시키지 않는 코드여도 알아서 고쳐준다!
addLetter: (state, action) => {
	  // 주석 부분이 불변성 유지를 위한 코드
      //const newLetter = action.payload;
      //return [newLetter, ...state];
      state.push(action.payload);
    },

 

action creator와 reducer 내보내기

위에서 만들어준 counterSlice에는 reducer 와 action creator 들이 저장되어 있다.

-  actions 객체안에 각 action creator 들을 구조 분해 할당으로 뜯어서 내보내줌.

   slice API에서 각각의 reducer를 추가하면 actions에 action들을 모아주는 것 같다. 

- counter reducer도 내보내준다. 

// 액션크리에이터는 컴포넌트에서 사용하기 위해 export 하고
export const { addNumber, minusNumber } = counterSlice.actions;

// reducer 는 configStore에 등록하기 위해 export default 합니다.
export default counterSlice.reducer;

 

 


 

configStore 설정 비교

 

모듈이 위에서 만든 counter와 todos로 2개 있다고 가정~!

 

일반 리덕스

combineReducers API로 각 reducer들을 하나의 객체로 묶어줘서 createStore 해줌.

- createStore API 사용 방식은 현재 권장하지 않고 있음 (vscode에서 보면 취소줄이 가있다)

// 일반 리덕스 combineReducers 예시 코드
// src/redux/config/configStore.js

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

const rootReducer = combineReducers({
  counter, //counter: counter, 의 생략
  todos,
});
const store = createStore(rootReducer);
export default store;

 

리덕스 툴킷

- slice reducer 들을 import 해와서 configureStore API로 reducer의 객체로 slice reducer들을 추가해줌

- store라는 큰 객체 안에 reducer가 있고 reducer는 또한번 객체로 각 slice reducer들을 가짐.

{ reducer : { a, b, c } }

 

- 일반 리덕스에서도 configureStore사용 가능

- combineReducers 필요 없음!

// src/redux/config/configStore.js

import { configureStore } from "@reduxjs/toolkit";
import counter from "../modules/counterSlice";
import todos from "../modules/todosSlice";

const store = configureStore({
  reducer: { counter: counter, todos: todos },
});

export default store;

 

반응형