<React> Redux toolkit

·2023년 8월 5일
0

React

목록 보기
18/23

Redux-Toolkit은 Redux의 몇 가지 특징을 단순화한 것이다.

Redix-Toolkit State 연결하기

store 파일에 createSlice 또는 createReducer를 import해줘야 합니다.

createSlice: 초기 상태, 리듀서 함수로 가득 찬 객체 및 "슬라이스 이름"을 받아들이고 리듀서 및 상태에 해당하는 액션 생성자와 액션 유형을 자동으로 생성하는 함수입니다.
학습한 강의에서는 createReducer보다 createSlice의 기능이 더 강력하다. 라고 나옴

createReducer: Redux 감속기 기능 생성을 간소화하는 유틸리티입니다.
내부적으로 Immer를 사용하여 리듀서에 "변형" 코드를 작성하여 불변 업데이트 로직을 크게 단순화하고 특정 액션 유형을 케이스 리듀서 함수에 직접 매핑하여 해당 액션이 발송될 때 상태를 업데이트하도록 지원합니다.

store.js

// configureStore를 이용하여 여러 reducer를 하나의 reducer로 쉽게 합칠 수 있습니다. 
// createSlice는 단일  reducer만 처리합니다.
import { createSlice, configureStore } from "@reduxjs/toolkit";

const initialState = {
  counter: 0,
  showCounter: true,
};

// counterSlice는 전역상태의 slice가 됩니다. 이 slice는 counter와 작동해야 합니다.
const counterSlice = createSlice({
  name: "counter",
  initialState,
  reducers: {
    increment(state) {
      state.counter++; // createSlice 메서드를 이용하면 redux의 기존 state를 바꿀 수 없습니다. 기존의 redux와 똑같이 최신 snapshot으로 덮어씌울뿐입니다.
    }, // 해당 메서드들은 나중에 리덕스에 의해 호출되고 현재 상태를 받습니다. 여기서는 action이 필요없습니다. 어떤 action을 했느냐에 따라 여기있는 메서드들이 호출되기 때문입니다.
    decrement(state) {
      state.counter--;
    }, // (위에 이어서) 대신 나중에 서로 다른 리듀서를 구별해놓고, 각각의 리듀서에 해당하는 action을 발생시킵니다.
    increase(state, action) {
      // payload 지정 (action을 지칭함)
      state.counter = state.counter + action.value; // state를 변경하는 것 처럼 보이지만, state를 변경하고 있지 않습니다. 새로운 값으로 덮어씌우는 겁니다.
    },
    toggleCounter(state) {
      state.toggleCounter = !state.toggleCounter;
    },
  }, // 리듀서는 객체 혹은 map이라 할 수 있다. 여기있는 slice는 리듀서를 필요로 한다. reducer의 값으로 들어가는 객체 안에 메서드를 추가하면 됩니다. 여기가 중요한 역할을 합니다.
}); // 객체를 인자로서 생성합니다. 해당 메서드로 전역 상태의 slice를 미리 만들어놔야 합니다. 여기서는 counter이름을 가진 slice를 생성합니다. createSlice 메서드를 이용하면 redux의 기존 state를 바꿀 수 없습니다. 최신 snapshot으로 덮어씌울뿐입니다.


// reducer : key : {reducer.name : 선언한_slice.reducer ... } 이런 방식으로 여러 슬라이스의 리듀서를 하나로 합칠 수 있습니다.
// store를 생성할 때, createStore(counterSlice.reducer)로 기입하면 slice에서 설정한 리듀서 하나에 접근할 수 있음.
// configureStore는 여러 리듀서를 묶어서 하나로 합칠 수 있음. 이 때, 넘겨주는 값은 리듀서 함수가 아니라 객체를 넘겨줘야 한다.
// createStore는 하나의 리듀서를 처리함.
const store = configureStore({
  reducer: counterSlice.reducer,
});

// reducer영역에 있는 메서드에 접근하기 위해서는 `counterSlice.action.REDUCER_METHOD`식으로 접근하면 됩니다.
// 아래와 같이 메서드를 불러오면, '액션 생성자'로 불립니다. 액션 객체를 생성해주기 때문입니다.
// 이런 객체는 이미 액션마다 다른 고유 식별자와 함께 type 속성을 가지고 있습니다. 자동으로 처리되기 때문에 액션 식별자에 대해 신경 쓸 필요가 없다.
// 이렇게 하고 액션이 필요한 컴포넌트로 넘어가면 됩니다.
export const counterActions = counterSlice.actions;

export default store;

Counter.jsx

import { useSelector, useDispatch } from "react-redux";

import { counterActions } from "../store/index"; 
// 리듀서 메서드 이름들을 key로 가진 객체입니다.

import classes from "./Counter.module.css";

const Counter = () => {
  const dispatch = useDispatch();
  // dispatch가 store에서 state와 action을 가지고 있는 객체임.
 
  const counter = useSelector((state) => state.counter);
  const show = useSelector((state) => state.showCounter);
  // 리덕스가 관리하는 state를 받고, 우리가 추출하려는 state 부분을 return한다.
  // useSelector는 store에 있는 기본 state 상태 ~ 최신화 된 상태를 바로 사용할 수 있게 해준다.

  const incrementCounter = () => {
    dispatch(counterActions.increment());
  };

  const decrementCounter = () => {
    dispatch(counterActions.decrement());
  };

  const increaseCounter = () => {
    // action payload를 보내줄 때는 생성자 함수 안에 값을 넣어서 전달해주면 된다.
    // 이 때, store에서 받는 값을 꼭 payload라고 명시해줘야한다.
    // payload 이름으로 추가 데이터가 전달되기 때문임.
    dispatch(counterActions.increase(5));
  };

  const toggleCounterHandler = () => {
    dispatch(counterActions.toggleCounter());
  };

  return (
    <main className={classes.counter}>
      <h1>Redux Counter</h1>
      {show && <div className={classes.value}>{counter}</div>}
      <div className={classes.button}>
        <button onClick={incrementCounter}>+</button>
        <button onClick={increaseCounter}>+5</button>
        <button onClick={decrementCounter}>-</button>
      </div>
      <button onClick={toggleCounterHandler}>Toggle Counter</button>
    </main>
  );
};

export default Counter;

✅ 아래 설명은 store.js 코드를 기준으로 작성합니다.

1️⃣ import { createSlice, configureStore } from "@reduxjs/toolkit"부분입니다.

  • configureStore를 이용하여 여러 reducer를 하나의 reducer로 쉽게 합칠 수 있습니다.

2️⃣ const counterSlice = createSlice({}) 부분입니다.

  • counterSlice는 전역상태의 slice가 됩니다. 이 slice는 counter와 작동해야 합니다.
  • 객체를 인자로서 생성합니다. 해당 메서드로 전역 상태의 slice를 미리 만들어놔야 합니다. 여기서는 counter이름을 가진 slice를 생성합니다. createSlice 메서드를 이용하면 redux의 기존 state를 바꿀 수 없습니다. 최신 snapshot으로 덮어씌울뿐입니다.
  • createSlice 메서드를 이용하면 redux의 기존 state를 바꿀 수 없습니다. 기존의 redux와 똑같이 최신 snapshot으로 덮어씌울뿐입니다.

3️⃣ reducers : {imcrement(state) {...} ...} 부분입니다.

  • 해당 메서드들은 나중에 리덕스에 의해 호출되고 현재 상태를 받습니다. 동적인 값을 전달받지 않는다면 action을 지정하지 않아도 됩니다.
  • 동적인 값을 전달해야한다면 action을 추가해야합니다. 어떤 action을 했느냐에 따라 여기있는 메서드들이 호출되기 때문입니다.
    위 코드의 increse(state, action)이 예시입니다.

4️⃣ const store = configureStore({ reducer: counterSlice.reducer, }); 부분입니다.

  • configureStore는 여러 리듀서를 묶어서 하나로 합칠 수 있음. 이 때, 넘겨주는 값은 리듀서 함수가 아니라 객체를 넘겨줘야 한다.
    createStore는 하나의 리듀서를 처리함.
  • reducer : key : {reducer.name : 선언한_slice.reducer ... } 이런 방식으로 여러 슬라이스의 리듀서를 하나로 합칠 수 있습니다.
  • store를 생성할 때, createStore(counterSlice.reducer)로 기입하면 slice에서 설정한 리듀서 하나에 접근할 수 있음.
    createStore ➡️ 단일 리듀서 사용시
    configureStore ➡️ 여러 리듀서를 사용할 수 있게 하나로 합쳐줌
  • reducer영역에 있는 메서드에 접근하기 위해서는 counterSlice.action.REDUCER_METHOD식으로 접근하면 됩니다.

    아래와 같이 메서드를 불러오면, 액션 생성자로 불립니다.
    counterSlice.action.increment (메서드 이름만 불러옵니다.)
    액션 객체를 생성해주기 때문입니다.
    이런 객체는 이미 액션마다 다른 고유 식별자와 함께 type 속성을 가지고 있습니다.
    자동으로 처리되기 때문에 액션 식별자에 대해 신경 쓸 필요가 없습니다.

5️⃣ export const counterActions = counterSlice.actions; 부분입니다.

  • reducer영역에 있는 메서드에 접근하기 위해서는 counterSlice.action.REDUCER_METHOD식으로 접근하면 됩니다.
  • 위와 같이 메서드를 불러오면, 액션 생성자로 불립니다.
    액션 객체를 생성해주기 때문입니다.
  • 이런 객체는 이미 액션마다 다른 고유 식별자와 함께 type 속성을 가지고 있습니다. 자동으로 처리되기 때문에 액션 식별자에 대해 신경 쓸 필요가 없다.
  • 이렇게 하고 액션이 필요한 컴포넌트로 넘어가면 됩니다.

기존 리덕스와 비교하였을 때, 리덕스 툴킷을 사용하하여 액션 생성자로 액션 객체를 생성함으로 얻는 이점이 있다.

  1. 액션 객체를 생성하는 작업을 생략할 수 있다.
  2. 고유한 식별자를 생각해내는 작업을 생략할 수 있다.
  3. 오타에 대해 걱정할 필요가 없어진다.
  4. 훨씬 짧고 간결하며, 유지보수가 더욱 쉬워졌다.
  5. 액션 생성자 메서드에 인자를 넣으면 편하게 payload를 전달할 수 있다.

이전 게시물_ Redux State를 올바르게 사용하는 방법을 읽고 오면 redux-toolkit이 얼마나 편한지 이해될 수 있습니다.

Redux-toolkit 추가적인 학습 도움 자료

0개의 댓글