«   2024/09   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
Archives
Today
Total
Recent Posts
Recent Comments
관리 메뉴

뉴히의 개발 로그

[TIL] 20230802 - TypeScript & redux toolkit : createSlice payload 타입 정의해 주기 PayloadAction 타입 본문

개발일지/TIL

[TIL] 20230802 - TypeScript & redux toolkit : createSlice payload 타입 정의해 주기 PayloadAction 타입

뉴히 2023. 8. 2. 20:02
import { createSlice } from '@reduxjs/toolkit';
import { Todo } from '../../model/todo';
import shortid from 'shortid';

const initialState: Todo[] = [
    {
        id: shortid.generate(),
        title: '타입스크립트 lv2과제',
        contents: '리덕스 툴킷 사용 Todo 리스트 typescript로 만들기',
        isDone: false
    },
    {
        id: shortid.generate(),
        title: '타입스크립트 lv1과제',
        contents: 'react lv1 과제 typescript로 만들기',
        isDone: true
    }
];

const todoListSlice = createSlice({
    name: 'todoList',
    initialState: initialState,
    reducers: {
        addTodo: (state, action) => {
            return [...state, action.payload];
        },
        delTodo: (state, action) => {
            return state.filter((todo) => todo.id !== action.payload);
        },
        switchTodo: (state, action) => {
            return state.map((todo) => {
                if (todo.id === action.payload) {
                    return { ...todo, isDone: !todo.isDone };
                }
                return todo;
            });
        }
    }
});

export default todoListSlice.reducer;
export const { addTodo, delTodo, switchTodo } = todoListSlice.actions;

payload 타입은 any로 자동으로 타입스크립트가 만들어준다. (타입은 선언안하면 any가됨!)

그래서 addTodo의 경우는 선언해둔 type Todo를 넣으면 되겟지?

 

응 안됨

ㅋㅋㅋㅋㅋㅋ

 

리덕스 툴킷에서 제공하는 PayloadAction 타입을 사용하면 쉽다!

 

import { PayloadAction, createSlice } from '@reduxjs/toolkit';
import { Todo } from '../../model/todo';
import shortid from 'shortid';

const initialState: Todo[] = [
    {
        id: shortid.generate(),
        title: '타입스크립트 lv2과제',
        contents: '리덕스 툴킷 사용 Todo 리스트 typescript로 만들기',
        isDone: false
    },
    {
        id: shortid.generate(),
        title: '타입스크립트 lv1과제',
        contents: 'react lv1 과제 typescript로 만들기',
        isDone: true
    }
];

const todoListSlice = createSlice({
    name: 'todoList',
    initialState: initialState,
    reducers: {
        addTodo: (state, action: PayloadAction<Todo>) => {
            return [...state, action.payload];
        },
        delTodo: (state, action: PayloadAction<string>) => {
            return state.filter((todo) => todo.id !== action.payload);
        },
        switchTodo: (state, action: PayloadAction<string>) => {
            return state.map((todo) => {
                if (todo.id === action.payload) {
                    return { ...todo, isDone: !todo.isDone };
                }
                return todo;
            });
        }
    }
});

export default todoListSlice.reducer;
export const { addTodo, delTodo, switchTodo } = todoListSlice.actions;

PayloadAction

PayloadAction은 Redux Toolkit에서 제공하는 유틸리티 타입 중 하나로, 액션의 페이로드(payload)를 포함하는 표준화된 액션 객체를 생성하는 데 사용됩니다. 일반적으로 Redux에서는 액션 객체에 typepayload라는 프로퍼티를 포함시켜 액션을 정의합니다. Redux Toolkit은 이를 간소화하여 PayloadAction을 사용하여 편리하게 액션을 생성하고 다룰 수 있도록 도와줍니다.

type PayloadAction<P = any, T extends string = string, M = never, E = never> = {
  payload: P;
  type: T;
} & ([M] extends [never] ? {} : { meta: M }) & ([E] extends [never] ? {} : { error: E });
  • P: 액션의 페이로드(payload)의 타입을 나타내는 제네릭(Generic)입니다.
  • T: 액션의 타입(type)을 나타내는 제네릭(Generic)입니다. 기본적으로 문자열 타입으로 지정되지만 필요에 따라 다른 타입을 지정할 수 있습니다.
  • M: 액션의 메타데이터(meta)를 나타내는 제네릭(Generic)입니다. 기본적으로 never로 지정되어 있으며, 추가적인 메타데이터가 필요할 때 사용됩니다.
  • E: 액션의 에러(error)를 나타내는 제네릭(Generic)입니다. 기본적으로 never로 지정되어 있으며, 에러를 나타내는 액션을 처리할 때 사용됩니다.

Redux Toolkit의 createSlice 함수를 사용하여 리듀서와 액션을 생성할 때 PayloadAction을 함께 사용합니다. 액션의 페이로드를 명시하면, 리듀서에서 해당 액션을 처리할 때 페이로드에 접근할 수 있습니다.