여러 개의 reducer 사용하기 (combineReducer)

최경락 (K_ROCK_)·2022년 6월 7일
1

개요

  • redux 연습을 하면서 먼저 가장 간단한 카운터 기능을 구현하였지만, 같은 프로젝트 내에서 배열, 문자열, 객체 등 다른 데이터들도 다뤄보고 싶었다!
  • 하나의 파일에 여러 reducer, action 등을 몰아서 작성하는 방법을 사용 할 수 있지만, 작성하는 김에 컴포넌트 별 action, reducer 를 나누어 가독성에 좋게 파일구조를 작성해보면 좋을 것 같았다.
  • 하지만 그렇게 되면 reducer 가 2개 이상 생기게 되는데, 이 때 어떻게 작성하는 지에 대해 정리해보고자 한다.

새로운 전역상태 만들기

  • Array 라는 컴포넌트에 문자열로만 이루어진 간단한 Todo 기능을 만들고, 해당 배열을 전역상태로 만들어 다뤄보려 한다.

types

  • 간단하게 추가, 삭제, 초기화 세 가지의 기능을 구현하기로 하고, 각각에 맞는 action type 을 지정해주었다.
// types.ts

export const ADD_ELEM = 'ADD_ELEM';
export const REMOVE_ELEM = 'REMOVE_ELEM';
export const CLEAR_ELEM = 'CLEAR_ELEM';

actions

  • 추가 및 삭제를 구현하기 위해 인자의 값이 필요했고, 매개변수와 해당 매개변수의 타입을 지정하여 원하는 데이터를 받는다.
  • 여기서 지정된 매개변수는 dispatch(action 이름(인자)); 을 이용하여 인자의 값을 저장한다.
  • 이때, type 외의 데이터는 payload 에 담아 전달해야한다.
// actions.ts

import { ADD_ELEM, REMOVE_ELEM, CLEAR_ELEM } from './types';
// 지정한 action type 을 불러온다.

export const addElem = (value: string) => {
  return {
    type: ADD_ELEM,
    payload: {
      value,
      // value : value 와 동일하다.
    },
  };
};

export const removeElem = (idx: number) => {
  return {
    type: REMOVE_ELEM,
    payload: {
      idx,
    },
  };
};

export const clearElem = () => {
  return {
    type: CLEAR_ELEM,
  };
};

reducer

  • 해당 컴포넌트에서 사용할 초기 상태 값을 지정하고, action 이 전달하는 값들의 타입을 지정한다.
    type 뿐만 아니라, payload 가 전달하는 값들 또한 타입을 지정해줘야한다.
  • 이전에 작성한 counterReducer 와 마찬가지로 export 해준다.
// reducer.ts

import { ADD_ELEM, REMOVE_ELEM, CLEAR_ELEM } from './types';
// action type 을 가져온다.

const initialState = {
  arr: ['기본데이터1', '기본테이터 2'],
};

const arrayReducer = (
  state = initialState,
  action: { type: string; payload: { value: string; idx: number } }
) => {
  switch (action.type) {
    case ADD_ELEM:
      return {
        ...state.arr,
        arr: [...state.arr, action.payload.value],
      };

    case REMOVE_ELEM:
      return {
        ...state.arr,
        arr: state.arr.filter((el, idx) => {
          return idx !== action.payload.idx;
        }),
      };

    case CLEAR_ELEM:
      return {
        ...state.arr,
        arr: [],
      };

    default:
      return state;
  }
};

export default arrayReducer;

store

  • combineReducers 함수를 이용하여 만들어진 reducer 들을 내보낸다.

combineReducers

  • 여러 reducer 들을 하나의 store 에 저장 할 수 있게 해주는 함수이다.
  • combineReducers 의 첫번째 인자에 객체 형태로 원하는 reducer 를 작성하고, 변수에 저장한다.
  • 해당 변수를 createStore의 인자로 사용하면 다수의 reducerstore로 전달 할 수 있다.
// store.ts

import {
  combineReducers,
  legacy_createStore as createStore,
} from '@reduxjs/toolkit';

import counterReducer from './counter/reducer';
import arrayReducer from './array/reducer';
// 필요한 reducer 를 불러온다.

const reducer = combineReducers({
  counterReducer,
  arrayReducer,
});

const store = createStore(reducer);

export default store;
  • console.log(store.getState()); 를 이용하여 전체 상태를 확인 할 수 있으며, 그 출력은 아래와 같다.
{
  counterReducer: {}, 
  arrayReducer: {}
}
  • store.getState()store에 저장된 모든 상태를 반환한다.
  • 만약 데이터를 저장하는 상태의 이름을 바꾸고자 하는 경우에는 아래와 같이 작성하면 된다.
const reducer = combineReducers({
  data1 : counterReducer,
  data2 : arrayReducer,
});
  • 이 경우 출력은 아래와 같아진다.
{
  data1: {}, 
  data2: {}
}

+

  • 현재는 컴포넌트 별로 폴더를 만들어 actions, reducer 를 관리하고 있지만, actions, reducer 각각 폴더를 만들어 몰아서 관리하는 방법도 고려해보고 연습해봐야겠다!

0개의 댓글