본문 바로가기
typescript

[typescript] typesafe-actions 라이브러리

by 남민섭 2023. 2. 24.
728x90
반응형

typesafe-actions 라이브러리 적용하기

리덕스 모듈을 굉장히 짧게 코드를 줄여줌

 

리덕스 모듈 구조

액션타입/ 액션생성함수/ 리듀서/상태타입

 

설치

npm install typesafe-actions

 

1. 액션 타입 변경

const INCREASE = "counter/INCREASE" as const   →   const INCREASE = "counter/INCREASE"  

 

2. 액션 생성 함수

구문)

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


createStandardtAction(액션타입)<전달받은 값 타입>

createAction(액션타입)

action()함수는 액션객체를 만드는 함수

액션타입정의

구문 ex)

import { ActionType } from "typesafe-actions";

const actions = {increase, decrease};

 

 

 

파라미터와 payload값의 형태가 다를 때

파라미터를 기반으로 커스텀마이징 된 payload설정일때

음... 그러니깐  전달 받은 타입과 payload(전달받은)타입이 일치하는 경우

createStandartAction(액션타입)<전달받은 값 타입> 사용

 

 

전달받은 타입과 payload(전달 받은)타입이 다를 경우

createAction(액션타입) 사용

 

예시)

type-action 적용 전

export const addTodo = (text:string) => ({
    type: ADD_TODO, 
    payload: {
        id: nextId++, 
        text: text
    }
})

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

export const removeTodo = (id:number) => ({
    type: REMOVE_TODO,
    payload: id
})

type-action 적용 후

//2.액션 생성 함수
export const addTodo = createAction(ADD_TODO, action => (text:string)=>
    action({
        id: nextId++,
        text: text
    })
)
export const toggleTodo = createStandardAction(TOGGLE_TODO)<number>();
export const removeTodo = createStandardAction(REMOVE_TODO)<number>();

//액션타입정의
const actions = {addTodo, toggleTodo, removeTodo}
type TodoAction = ActionType<typeof actions>

 

3.리듀서 생성함수(todolist예시)

type-action 적용 전 

function todos(state: TodoState= initialState, action:TodoAction){
    switch(action.type){
        case ADD_TODO:
            return [
                ...state,
                {
                    id: action.payload.id,
                    text: action.payload.text,
                    isDone: false
                }
            ]
        case TOGGLE_TODO:
            //이전상태 배열을 순환하며 배열 요소의 id값과 action의 payload일치하는지
            //값이 일치하면 요소의 isDone을 반전해서 리턴
            //일치하지 않으면 배열요소 리턴
            return state.map(todo=>todo.id === action.payload ? 
                {...todo, isDone: !todo.isDone}: todo);
        case REMOVE_TODO:       
            return state.filter(todo=> todo.id !== action.payload)    
        default:
            return state    
    }
}

export default todos;

 

구문)

createReducer<상태타입, 액션타입>(초기상태값, {
	[액션타입1]:(state, action)=> 리턴값,
	[액션타입2]:(state, {payload: id}) => 리턴값,
	[액션타입3]:(state, {payload: id}) => 리턴값
})

 

type-action 적용 후 

//3. 리듀서 함수 - state타입 action타입지정
const todos = createReducer<TodoState, TodoAction>(initialState, {
    [ADD_TODO]: (state, action) =>
    [...state, {...action.payload, isDone:false}],
    [TOGGLE_TODO]: (state, {payload: id}) => state.map(todo=>todo.id === id ? 
        {...todo, isDone: !todo.isDone}: todo),
    [REMOVE_TODO]: (state, {payload: id}) => state.filter(todo=> todo.id !== id)     
})
export default todos;

모듈 전체 변경전

//1.액션타입
//type-action 적용전
const ADD_TODO = "todos/ADD_TODO" as const
const REMOVE_TODO = "todos/REMOVE_TODO" as const
const TOGGLE_TODO = "todos/TOGGLE_TODO" as const



//t새로운 항목 추가할때 사용할 id값
let nextId = 1;


//2.액션 생성 함수
export const addTodo = (text:string) => ({
    type: ADD_TODO, 
    payload: {
        id: nextId++, 
        text: text
    }
})

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

export const removeTodo = (id:number) => ({
    type: REMOVE_TODO,
    payload: id
})


//ReturnType<typeof addTodo> 특정함수의 리턴타입을 추론
type TodoAction = ReturnType<typeof addTodo> 
| ReturnType<typeof removeTodo> 
|ReturnType<typeof toggleTodo> 





//상태에서 사용할 할일 항목의 타입정의
export type Todo ={
    id: number;
    text: string;
    isDone: boolean;
}
//상태에 대한 타입
export type TodoState = Todo[]

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

//3. 리듀서 함수 - state타입 action타입지정
//type-action 적용전
function todos(state: TodoState= initialState, action:TodoAction){
    switch(action.type){
        case ADD_TODO:
            return [
                ...state,
                {
                    id: action.payload.id,
                    text: action.payload.text,
                    isDone: false
                }
            ]
        case TOGGLE_TODO:
            //이전상태 배열을 순환하며 배열 요소의 id값과 action의 payload일치하는지
            //값이 일치하면 요소의 isDone을 반전해서 리턴
            //일치하지 않으면 배열요소 리턴
            return state.map(todo=>todo.id === action.payload ? 
                {...todo, isDone: !todo.isDone}: todo);
        case REMOVE_TODO:       
            return state.filter(todo=> todo.id !== action.payload)    
        default:
            return state    
    }
}

export default todos;

모듈 전체 변경후

//액션 생성, 액션 생성함수, 리듀서
import { ActionType, createReducer, deprecated  } from "typesafe-actions";
const {createStandardAction, createAction} = deprecated;

//1.액션타입
const ADD_TODO = "todos/ADD_TODO" 
const REMOVE_TODO = "todos/REMOVE_TODO" 
const TOGGLE_TODO = "todos/TOGGLE_TODO" 


//t새로운 항목 추가할때 사용할 id값
let nextId = 1;


//2.액션 생성 함수
export const addTodo = createAction(ADD_TODO, action => (text:string)=>
    action({
        id: nextId++,
        text: text
    })
)
export const toggleTodo = createStandardAction(TOGGLE_TODO)<number>();
export const removeTodo = createStandardAction(REMOVE_TODO)<number>();

const actions = {addTodo, toggleTodo, removeTodo}
type TodoAction = ActionType<typeof actions>



//상태에서 사용할 할일 항목의 타입정의
export type Todo ={
    id: number;
    text: string;
    isDone: boolean;
}

//상태에 대한 타입
export type TodoState = Todo[]

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

//3. 리듀서 함수 - state타입 action타입지정
const todos = createReducer<TodoState, TodoAction>(initialState, {
    [ADD_TODO]: (state, action) =>
    [...state, {...action.payload, isDone:false}],
    [TOGGLE_TODO]: (state, {payload: id}) => state.map(todo=>todo.id === id ? 
        {...todo, isDone: !todo.isDone}: todo),
    [REMOVE_TODO]: (state, {payload: id}) => state.filter(todo=> todo.id !== id)     
})
export default todos;

 

다시 정리해보자면.....

더보기

typesafe-actions 라이브러리 적용하기
*리덕스 모듈을 좀더 간결하게 작성


액션타입, 액션생성함수, 리듀서 함수, 상태타입


1.액션타입
const INCREASE = "counter/INCREASE" as const
-=> const INCREASE = "counter/INCREASE"  바뀜


2. 액션생성함수
*액션타입에 type속성만 있는경우
createStandardAction(액션타입)();
*액션객체에 전달하는 속성이 있는 경우(payload 속성이 있는 경우)


1) 전달 받은 타입과 payload타입이 일치하는 경우

ex)
ToggleTodo(1) ---> dispatch({type: TOGGLE_TODO, payload: 1}) << 이 상황일 경우(payload 타입이 일치하는 경우)

createStandardAction(액션타입)<payload값 타입>

ADDTodo("리액트포톨만들기") ====> dispatch({type:ADD_TODO, payload: {id:2, text: "리액트포폴만들기"}})


2) 전달받은 타입과 payload타입이 다를 경우
createAction(액션타입, action => (text:string) => 
     action({id: 2, text: text})
)

3. 액션 객체에 대한 타입
const actions = {액션생성함수1, 액션생성함수2...}
type TodoAction = ActionType<typeof action>

4. 리듀서
const todos = createReducer<액션타입, 액션타입>(상태초기값, {
     [액션타입1]: (state, action) => 상태리턴,
     [액션타입2]: (state, action) => 상태리턴
})

728x90
반응형

댓글