Web/[JS] FrontEnd

Redux ducks 패턴 with Typescript

ihl 2021. 4. 30. 19:35

Redux structure

  React에서 상태관리를 하기 위한 대표적인 라이브러리는 Redux이다. 리덕스는 위와 같이 Store, Dispatch, Reducer, Action으로 되어있어  하나의 상태를 저장하는 리덕스도 4개의 파일이 나오게되며 기존 리덕스에 하나의 액션을 추가하려면 3개의 파일을 수정해야한다. 이 것이 불편하다고 생각했던 사람들은 구조가 아닌 기능을 기준으로 파일을 분리하기로 하였다. 이 것이 Ducks 패턴이다.

 

1. 규칙

  Ducks 패턴은 하나의 상태에 필요한 액션 타입, 액션생성자 함수, 리듀서를 한 파일에 저장한다. 따라서 하나의 액션이 추가되면 하나의 파일이 추가될 뿐이다. 구체적인 규칙은 다음과 같다.

  1. 반드시 reducer란 이름의 함수를 export default 한다.
  2. 반드시 action 생성자들을 함수로 export 한다.
  3. 반드시 액션은 앱이름/reducer이름/Action_type 형태여야 한다.
  4. 액션 타입을 UPPER_SNAKE_CASE와 같이 export 할 수 있다.

2. 구현 예시

 

erikras/ducks-modular-redux

A proposal for bundling reducers, action types and actions when using Redux - erikras/ducks-modular-redux

github.com

  React에서 ducks패턴을 어떻게 구현하는지 잘 나온 예시 깃허브링크이다. 참고해서 만들면 된다.

 

3. TypeScript

import { createAction, ActionType, createReducer  } from 'typesafe-actions';

export interface userInfoState {
  id: number,
  name: string,
  city?: string
}

const initialState: userInfoState = {
  id: 0,
  name: ''
};

//Action type 정의
const changeUserInfo = 'ttmk/UserInfo/LOGIN'; //'앱이름/reducer이름/Acction_type' 형태
const changeInfoByGPS = 'ttmk/UserInfo/GPS';

//Action 생성자 정의 및 export
export const UserInfoHandler = createAction(userInfo)<userInfoState>();
export const LocationInfoHandler = createAction(changeInfoByGPS)<string>();

const actions = {UserInfoHandler, LocationInfoHandler};

export type UserInfoAction = ActionType<typeof actions>

const UserInfoReducer = createReducer<userInfoState, UserInfoAction>(initialState, {
  [changeUserInfo]: (state, action) => {
    return Object.assign({}, state, {
      'id': action.payload.id,
      'name': action.payload.name,
      'city': state.city
    });
  },
  [changeInfoByGPS]: (state, action) => {
    return Object.assign({}, state, {
      'id': state.id,
      'name': state.name,
      'city': action.payload
    });
  }
});

export default UserInfoReducer;

  내 나름대로 TypeScript에서 Ducks패턴을 구현해보았다.