노력이 좋아서

<step91>'react(redux)_ts(typesafe-action)_todoList'

zoaseo 2022. 7. 29. 15:20

2022.07.29 - [공부가 좋아서] - 'react(redux)_ts_todoList'

 

<step91>'react(redux)_ts_todoList'

2022.07.28 - [공부가 좋아서] - 'react(redux)_ts_counter' 'react(redux)_ts_counter'" data-og-description="1) npm create-react-app ts-redux-tutorial --template typescript npm install redux npm install..

zoaseo.tistory.com

1)

npm install typesafe-action

https://github.com/piotrwitek/typesafe-actions/issues/143

 

v5.0.0 - Rewrite and simplify `createAction` API · Issue #143 · piotrwitek/typesafe-actions

Is your feature request related to a real problem or use-case? Currently, createAction API is not optimal and require some unnecessary boilerplate code (historically it was created pre TS v3.0 so t...

github.com

modules.counter2.ts

// 1. 액션타입
// 2. 액션을 리턴해주는 함수
// 3. 초기값
// 4. 리듀서 만들기

import { ActionType, createReducer, deprecated } from "typesafe-actions";
const { createStandardAction } = deprecated;

const INCREASE = "counter/INCREASE" 
const DECREASE = "counter/DECREASE"
const INCREASE_BY = "counter/INCREASE_BY" 

// 액션 생성 함수
export const increase = createStandardAction(INCREASE)();
export const decrease = createStandardAction(DECREASE)();
export const increaseBy = createStandardAction(INCREASE_BY)<number>();

// 스테이트의 타입을 지정
type CounterState = {
    count: number;
}
// 초기상태 생성
const initialState = {
    count: 0
}
// 리듀서 액션 타입 지정
const actions = { increase, decrease, increaseBy }
type CounterAction = ActionType<typeof actions>

// 리듀서 만들기
// createReducer를 통해서 오브젝트 맵 형태로 리듀서를 구현
const counter2 = createReducer<CounterState, CounterAction>(initialState, {
    [INCREASE]: state => ({ count: state.count + 1}),
    [DECREASE]: state => ({ count: state.count - 1}),
    [INCREASE_BY]: (state, action) => ({ count: state.count + action.payload})
})
export default counter2;

modules/todos2.ts

// 액션 타입 선언, 액션 생성 함수, 초기값, 리듀서
// 할 일 추가, 할 일 제거, 할 일 체크

import { ActionType, createReducer, deprecated } from "typesafe-actions";
const { createStandardAction } = deprecated;
// 액션 타입 선언
const ADD_TODO = 'todos/ADD_TODO' as const;
const TOGGLE_TODO = 'todos/TOGGLE_TODO' as const;
const REMOVE_TODO = 'todos/REMOVE_TODO' as const;

let nextId = 1;
// 액션 생성 함수
export const addTodo:any = (text: string) => ({
    type: ADD_TODO,
    payload: {
        id: nextId++,
        text
    }
})
export const toggleTodo = createStandardAction(TOGGLE_TODO)<number>();
export const removeTodo = createStandardAction(REMOVE_TODO)<number>();

// 액션 객체들에 대한 타입 작성
const actions = {
    addTodo,
    toggleTodo,
    removeTodo
}
// 모든 액션 객체들에 대한 타입준비
// 함수의 리턴타입을 추론
type TodosAction = ActionType<typeof actions>
// 상태에서 사용할 할 일 항목 데이터 정의
export type Todo = {
    id: number;
    text: string;
    done: boolean;
}  
// 이 모듈에서 관리할 상태 타입 작성
export type TodoState = Todo[]

// 초기상태 선언
const initialState: TodoState = [];

// 리듀서 작성하기
const todos2 = createReducer<TodoState, TodosAction>(initialState, {
    [ADD_TODO]: (state, action) => {
        return state.concat({
            ...action.payload,
            done: false
        })
    },
    [TOGGLE_TODO]: (state,{ payload: id}) => 
    state.map(todo => (todo.id === id ? {...todo, done: ! todo.done} : todo)),
    [REMOVE_TODO]: (state,{ payload: id }) => 
    state.filter(todo => todo.id !== id)
})
export default todos2;

 

2)

modules/todos2.ts의 파일 쪼개기

modules/todos/action.ts

import { deprecated } from "typesafe-actions";
const { createStandardAction } = deprecated;

// 액션 타입 선언
export const ADD_TODO = 'todos/ADD_TODO';
export const TOGGLE_TODO = 'todos/TOGGLE_TODO';
export const REMOVE_TODO = 'todos/REMOVE_TODO';

let nextId = 1;
// 액션 생성 함수
export const addTodo:any = (text: string) => ({
    type: ADD_TODO,
    payload: {
        id: nextId++,
        text
    }
})
export const toggleTodo = createStandardAction(TOGGLE_TODO)<number>();
export const removeTodo = createStandardAction(REMOVE_TODO)<number>();

modules/todos/index.ts

export { default } from './reducer';
export * from './actions';
export * from './types';
console.log('aaa');

modules/todos/reducer.ts

import { TodoState, TodosAction } from "./types";
import { createReducer } from "typesafe-actions";
import { ADD_TODO, TOGGLE_TODO, REMOVE_TODO } from "./actions";

// 초기상태 선언
const initialState: TodoState = [];

// 리듀서 작성하기
const todos2 = createReducer<TodoState, TodosAction>(initialState, {
    [ADD_TODO]: (state, action) => {
        return state.concat({
            ...action.payload,
            done: false
        })
    },
    [TOGGLE_TODO]: (state,{ payload: id}) => 
    state.map(todo => (todo.id === id ? {...todo, done: ! todo.done} : todo)),
    [REMOVE_TODO]: (state,{ payload: id }) => 
    state.filter(todo => todo.id !== id)
})
export default todos2;

modules/todos/types.ts

import { ActionType } from "typesafe-actions";
import * as actions from "./actions";

// 모든 액션 객체들에 대한 타입준비
// 함수의 리턴타입을 추론
export type TodosAction = ActionType<typeof actions>
// 상태에서 사용할 할 일 항목 데이터 정의
export type Todo = {
    id: number;
    text: string;
    done: boolean;
}  
// 이 모듈에서 관리할 상태 타입 작성
export type TodoState = Todo[]