Skip to content

Redux와 Typescript를 이용한 상태관리

yellow2041 edited this page Dec 20, 2020 · 4 revisions

우리 프로젝트의 Redux 구조

  • velopert님의 블로그 글을 참고하여 구현하였습니다.
  • 사용자가 선택한 콘서트의 정보를 저장하고 있습니다.
  • 규모가 크지 않아 모듈 안에서 액션, 액션 생성 함수, 리듀서를 한번에 정의하는 ducks패턴을 사용하였습니다.
  • modules/concertInfo.ts
const CHANGE_SELECTED_CONCERT = "concertInfo/CHANGE_SELECTED_CONCERT" as const;
const SELECT_SCHEDULE = "concertInfo/SELECT_SCHEDULE" as const;
const SET_CLASS_INFO = "concertInfo/SET_CLASS_INFO" as const;

export const changeSelectedConcert = (id: string, name: string) => ({
  type: CHANGE_SELECTED_CONCERT,
  payload: { id, name },
});

export const selectSchedule = (id: string, dateDetail: string) => ({
  type: SELECT_SCHEDULE,
  payload: { id, dateDetail },
});

export const setClassInfo = (prices: Object, colors: Object) => ({
  type: SET_CLASS_INFO,
  payload: { prices, colors },
});

export interface ConcertInfo {
  id: string;
  name: string;
  scheduleId?: string;
  dateDetail: string;
  prices: any;
  colors?: any;
  startDate?: string;
  endDate?: string;
  runningTime?: string;
  class?: string;
}

type ConcertInfoAction =
  | ReturnType<typeof changeSelectedConcert>
  | ReturnType<typeof selectSchedule>
  | ReturnType<typeof setClassInfo>;

type ConcertInfoState = ConcertInfo;

const initialState: ConcertInfoState = {
  id: "",
  name: "",
  scheduleId: undefined,
  dateDetail: "",
  prices: {},
  colors: undefined,
  startDate: undefined,
  endDate: undefined,
  runningTime: "",
  class: "",
};

const concertInfoReducer = (
  state: ConcertInfoState = initialState,
  action: ConcertInfoAction,
): ConcertInfoState => {
  switch (action.type) {
    case CHANGE_SELECTED_CONCERT:
      return {
        ...state,
        id: action.payload.id,
        name: action.payload.name,
      };
    case SELECT_SCHEDULE:
      return {
        ...state,
        scheduleId: action.payload.id,
        dateDetail: action.payload.dateDetail,
      };
    case SET_CLASS_INFO:
      return {
        ...state,
        prices: { ...action.payload.prices },
        colors: { ...action.payload.colors },
      };
    default:
      return state;
  }
};

export default concertInfoReducer;
  • modules/index.ts (루트리듀서 등록)
import { combineReducers } from "redux";
import concertInfoReducer from "./concertInfo";
import socketReducer from "./socket";
import userReducer from "./user";

const rootReducer = combineReducers({
  concertInfoReducer,
  userReducer,
  socketReducer,
});

export default rootReducer;

export type RootState = ReturnType<typeof rootReducer>;
  • hooks/useConcertInfo.ts
    • concertInfo의 상태를 자주 사용하기 때문에 hook을 만들어 사용하였습니다.
import { useSelector } from "react-redux";
import { RootState } from "../modules";

export default function useConcertInfo() {
  const concertInfo = useSelector((state: RootState) => state.concertInfoReducer);
  return concertInfo;
}

개선해야할 점

  • typescript의 장점을 활용하기 위해 interface 정의를 더 구체적으로 하기
    ex)
export interface ConcertInfo {
  id: string;
  name: string;
  scheduleId?: string;
  dateDetail: string;
  prices: any;
  colors?: any;
  startDate?: string;
  endDate?: string;
  runningTime?: string;
  class?: string;
}

이 부분의 개선 필요.

  • 처음에 redux 활용을 잘못해서 socket의 이벤트 등록과 관련된 부분을 context API로 대체하게 되었는데, 이 부분은 다시 redux로 대체 가능 할 것 같다.
Clone this wiki locally