Front-End

vsoghlv@naver.com

React.js 리덕스 모듈 여러 파일로 분리하기

이전에 작성했던 counter.ts 와 todos.ts 는 모두 한파일에 작성 되있는데 지금은 상관 없지만 후에 액션 타입등이 늘어나게 되면 관리하기가 매우 버거워진다고 한다.

그때를 위해 파일을 분리하는 방법을 배워보자.

modules
  todos
    action.ts
    index.ts
    reducer.ts
    types.ts

위와 같은 구성으로 작성하는 것을 추천한다고 한다.

//todos/action.ts
import { createAction } from "typesafe-actions";
import { Todo } from "./types";

export const ADD_TODO = "todos/ADD_TODO";
export const TOGGLE_TODO = "todos/TOGGLE_TODO";
export const REMOVE_TODO = "todos/REMOVE_TODO";

let nextId = 1;

//파라미터로 가져오는 값과 payload 가 다른 경우 createAction 을 사용하지 않는 것이 더 깔끔할 수 있다.
export const addTodo = createAction(ADD_TODO, (text: string) => ({
  id: nextId++,
  text: text,
}))<Todo>();
export const toggleTodo = createAction(TOGGLE_TODO)<number>();

export const removeTodo = createAction(REMOVE_TODO)<number>();

//todos/types.ts
import { ActionType } from "typesafe-actions";
import * as actions from "./action";

export type TodosAction = ActionType<typeof actions>;
export type Todo = {
  id: number;
  text: string;
  done: boolean;
};

//초기 상태에 대한 타입
export type TodosState = Todo[];

//todos/reducer.ts
import { createReducer } from "typesafe-actions";
import { ADD_TODO, REMOVE_TODO, TOGGLE_TODO } from "./action";
import { TodosAction, TodosState } from "./types";

const initialState: TodosState = [];
const todos = createReducer<TodosState, TodosAction>(initialState, {
  [ADD_TODO]: (state, action) =>
    state.concat({
      ...action.payload,
      done: false,
    }),
  [TOGGLE_TODO]: (state, action) =>
    state.map((todo) =>
      todo.id === action.payload ? { ...todo, done: !todo.done } : todo
    ),
  [REMOVE_TODO]: (state, action) =>
    state.filter((todo) => todo.id !== action.payload),
});

export default todos;

//todos/index.ts
import { createReducer } from "typesafe-actions";
import { ADD_TODO, REMOVE_TODO, TOGGLE_TODO } from "./action";
import { TodosAction, TodosState } from "./types";

const initialState: TodosState = [];
const todos = createReducer<TodosState, TodosAction>(initialState, {
  [ADD_TODO]: (state, action) =>
    state.concat({
      ...action.payload,
      done: false,
    }),
  [TOGGLE_TODO]: (state, action) =>
    state.map((todo) =>
      todo.id === action.payload ? { ...todo, done: !todo.done } : todo
    ),
  [REMOVE_TODO]: (state, action) =>
    state.filter((todo) => todo.id !== action.payload),
});

export default todos;