티스토리 뷰

thunk

thunk는 비동기라는 작업을 Redux에서 어떻게 다룰까 라는 생각으로 고안된 도구이다.

 

createAsyncThunk

비동기 작업을 처리하는 액션을 만들어준다. 비동기 액션 생성자이다.

이전 포스팅에서 NewChat을 POST하고 나서 서버데이터가 자동으로 업데이트되지 않는 문제가 있었다. 이를 해결하기 위해 thunk 라이브러리의 기능을 사용한다. 리덕스에서 비동기를 다루기 위해 redux-thunk, redux-saga 등의 라이브러리가 있는데 RTK에서 thunk를 공식적으로 사용하고 있어서 thunk 라이브러리의 기능인 createAsyncThunk 함수를 사용했다.

createSlice의 reducers을 통해 RTK가 액션생성자를 자동으로 만들어준다. 그런데 비동기작업에 대해서는 자동으로 만들지 못한다. 그래서 extraReducers에서 정의한다. 비동기 액션생성자를 사용하려면 createSlice의 extraReducers에 코드를 작성한다.

import axios from 'axios';

import { ERROR_GET_DATA } from '../utils/errorMessage';
import { IChat } from '../pages/Chats';
import { PayloadAction, createAsyncThunk, createSlice } from '@reduxjs/toolkit';
import { GPTEA_ACCESS_TOKEN } from '../utils/loginGpteaFunc';

interface IrequestGetChats {
  data: IChat[];
  status: string;
}

// 액션 생성자
export const requestGetChats = createAsyncThunk<IChat[]>('requestGetChats', async () => {
  try {
    const {
      data: { chats },
    } = await axios('/me/chats', {
      method: 'GET',
      headers: {
        Authorization: `Bearer ${localStorage.getItem(GPTEA_ACCESS_TOKEN)}`,
      },
    });
    return chats;
  } catch (err) {
    alert({ ERROR_GET_DATA, err });
  }
});

const requestGetChatsSlice = createSlice({
  name: 'requestGetChats',
  initialState: { data: [], status: 'none' } as IrequestGetChats,
  reducers: {},
  extraReducers: (builder) => {
    builder.addCase(requestGetChats.pending, (state, action) => {
      state.status = 'loading';
    }),
      builder.addCase(requestGetChats.fulfilled, (state, action: PayloadAction<IChat[]>) => {
        state.data = action.payload;
        state.status = 'success';
      }),
      builder.addCase(requestGetChats.rejected, (state, action) => {
        state.status = 'failure';
      });
  },
});

export default requestGetChatsSlice.reducer;

 

⛏ 에러

타입스크립트를 사용하면서 타입을 지정해주어야 하는 어려움이 있었다. 비동기 액션 생성자 함수가 반환하는 값(action.payload의 값)의 타입을 지정하면서 적절한 배열 인터페이스<IChat[]>를 할당해도 자꾸 빨간 줄이 떴다. 
타입을 지정하는 과정에서 발견한 문제인데, 
그동안 대부분의 코드에서 promise then-catch 문법을 많이 사용하였는데, 이렇게 하면 액션 생성자가 생성하는 액션의 payload에 then메서드에서 반환하는 값인 프로미스가 담긴다. 리듀서에서 이 payload를 그대로 리덕스 상태값으로 담아주기 때문에 프로미스를 반환하지 않고 값을 반환하도록 async/await을 사용해서 보다 간결하게 작성했다.

 

결과

 

🙌 github commit 🙌

 

feat: implement asynchronous GET chats using RTK-createAsyncThunk · evergarden0412/gptea-web@16e0b3b

Show file tree Showing 4 changed files with 70 additions and 24 deletions.

github.com

 

 

Reference

https://blog.ull.im/engineering/2019/03/10/logs-on-git.html

https://velog.io/@rkio/Typescript-React-Redux-toolkitft.-axios-%EB%93%B1%EB%93%B1-%ED%99%9C%EC%9A%A9

https://www.youtube.com/watch?v=K-3sBc2pUJ4&t=115s 

반응형
댓글