JavaScript에서 TypeScript로 코드 옮기기 - Redux reducer

LEEJAEJUN·2023년 5월 28일
0

react-typescript

목록 보기
5/7

JS → TS

WHAT

벨로퍼트 리액트 페이지의 리덕스 코드를 TypeScript로 옮기는 작업
수정된 전체 코드

WHY

벨로퍼트 페이지는 JavaScript를 기반으로 되어있다. 하지만 나는 TypeScript 공부중!!
그래서 리듀서 강의 코드를 최대한 혼자서 TypeScript로 옮기기로 결정했다.

HOW

그래도 DOIT 리액트 타입스크립트 책을 읽으면서 리듀서 공부를 해두었기 때문에 내가 JS로 코드를 짤 능력만 있으면 옮기는 것은 쉬울 거라고 생각했다.

  1. JS 코드 완벽히 익히기
    일단 JS 리덕스 코드를 연습했다. 아직 리덕스 공부가 부족하다고 느꼈기 때문이다.
    혼자서 구현할 수 있을 때까지 반복했다.

  2. 계획
    거창하게 말했지만 사실 별거 없다. 중요한 것은 놓치치 않는 '타입'.
    옮기면서 변수명이나 타입 선언에 집중했다.
    또, 타입이 생기기 때문에 파일 구조도 달리하는 쪽이 좋다고 생각했다. (아직 하진 않음)

  3. 옮기기
    이제 옮겨볼 차례다. 기존 코드와 비교, 주석을 자세히 보면서 읽어보자! <기존 코드>

// ** todos.ts **

// ** 1. 액션 생성기 타입 추가 **
type AddTodoAction = Action<typeof ADD_TODO> & {
  type: string;
  payload: Todo;
};

type ToggleTodoAction = Action<typeof TOGGLE_TODO> & {
  type: string;
  payload: number;
};

// ** 여러 타입이 있으면 하나의 Actions 타입으로 합쳐주는 게 좋다. **
type Actions = AddTodoAction | ToggleTodoAction;

// ** type을 설정하고 payload를 사용해서 나중에 dot annotation을 쓸 수 있게 한다. **
// ** 사실 이 부분은 아직 복습이 필요할 듯, 목적을 정확히 모르겠음. **
// ** 일단 payload를 쓰면 나중에 쓸 때 뭔가 유동적인 느낌적인 느낌. **
let nextId = 1;
export const addTodo = (title: string) => ({
  type: ADD_TODO,
  payload: {
    id: nextId++,
    title,
    done: false,
  },
});

export const toggleTodo = (payload: number) => ({
  type: TOGGLE_TODO,
  payload,
});

// ** todo 타입 정의 **
export interface Todo {
  title: string;
  id: number;
  done: boolean;
}

// ** initialState에도 type 추가 **
const initialState: Todo[] = [];

// ** 리듀서 수정하기 **
const todos = (state = initialState, action: Actions) => {
  switch (action.type) {
    case ADD_TODO:
      return [...state, action.payload];
    case TOGGLE_TODO:
      return state.map((item) =>
        item.id === action.payload ? { ...item, done: !item.done } : item
      );
    default:
      return state;
  }
};

export default todos;

힘들었던 점

사실 payload로 수정하고, 타입 추가하는 거 제외하면 다 동일하다.
그런데 useSelector에서 타입 선언하는 부분 그리고 addTodo 액션에서 payload에 id, title, done 세 가지 속성을 다 넣어야 한다는 사실이 헷갈렸다. 조금 더 해야하나 싶은데 솔직히 리덕스 너무 오래 붙잡고 있었다. 나중에 다시 돌아오자...🥹

// 2. TodosContainer.tsx
const todos = useSelector<AppState, Todo[]>((state) => state.todos);

// addTodo payload
let nextId = 1;
export const addTodo = (title: string) => ({
  type: ADD_TODO,
  payload: {
    id: nextId++,
    title,
    done: false,
  },
});

what to do next?

todos를 만들었으니 이제 counter를 추가할 예정이다. 그리고 폴더 구조도 좀 더 보기 쉽게 바꿔볼 예정. 근데 일단 진도 좀 나가고^^

참조

profile
always be fresh

0개의 댓글