리액트 - redux-thunk로 Promise다루기 - handleAsyncActions

정영찬·2022년 4월 23일
0

리액트

목록 보기
64/79
post-custom-banner

리듀서에서 액션타입에 따른 상태변화의 내용이 거의 비슷한 같은 내용으로 반복되는 것이 보이는데, 이를 handleAsyncActions 라는 유틸함수를 만들어서 리팩토링을 진행할 것이다

파라미터

type : 액션 타입
key : 변경된 상태값을 담아놓은 변수 이름 (posts, post)

리듀서의 내용을 대신하기 때문에 리듀서와 비슷하게 작성한다고 생각하면 수월하다.
타입의 뒷내용을 비구조화 할당으로 분리해서 선언하고, 리듀서의 형식대로 작성하되, 리턴으로 변경되는 데이터를 저장한 변수를 파라미터로 받아온 key 값으로 변경하면 끝이다.

export const handleAsyncActions = (type, key) => {
  const [SUCCESS, ERROR] = [`${type}_SUCCESS`, `${type}_ERROR`];
  return (state, action) => {
    switch (action.type) {
      case type:
        return {
          ...state,
          [key]: reducerUtils.loading(state.posts.data),
        };
      case SUCCESS:
        return {
            ...state,
            [key]: reducerUtils.success(action.payload)
        };
      case ERROR:
        return{
            ...state,
            [key]: reducerUtils.error(action.payload)      
          }
      default:
        return state;
    }
  };
};

이 함수를 사용하여 이전에 작성한 posts 모듈에서의 리듀서를 리팩토링 할 수 있다.

const getPostsReducer = handleAsyncActions(GET_POSTS, 'posts')
const getPostReducer = handleAsyncActions(GET_POST, 'post')

이 두가지 변수를 사용하면

posts 리듀서를

export default function posts(state, action) {
  switch (action.type) {
    case GET_POSTS:
    case GET_POSTS_SUCCESS:
    case GET_POSTS_ERROR:
        return getPostsReducer(state,action)
     
    case GET_POST:
    case GET_POST_SUCCESS:
    case GET_POST_ERROR:
        return getPostReducer(state,action)     

    default:
      return state;
  }
}

이렇게 변경이 가능해진다. getPosts의 경우에 해당하는 액션타입과 getPost에 해당하는 액션타입을 하나로 묶어서 리턴 값으로 유틸함수를 사용한 변수를 지정하면 된다.

현재 posts.js 모듈의 내용은 훨신 더 짧아졌다.

import * as postsAPI from "../api/posts";
import { createPromiseThunk, handleAsyncActions, reducerUtils } from "../lib/asyncUtils";

const GET_POSTS = "GET_POSTS";
const GET_POSTS_SUCCESS = "GET_POSTS_SUCCESS";
const GET_POSTS_ERROR = "GET_POSTS_ERROR";

const GET_POST = "GET_POST";
const GET_POST_SUCCESS = "GET_POST_SUCCESS";
const GET_POST_ERROR = "GET_POST_ERROR";

/*thunk 생성 함수*/
export const getPosts = createPromiseThunk(GET_POSTS, postsAPI.getPosts)

export const getPost = createPromiseThunk(GET_POST,postsAPI.getPostById)

const initialState = {
  posts: reducerUtils.initial(),
  post: reducerUtils.initial()
};

const getPostsReducer = handleAsyncActions(GET_POSTS, 'posts')
const getPostReducer = handleAsyncActions(GET_POST, 'post')
export default function posts(state, action) {
  switch (action.type) {
    case GET_POSTS:
    case GET_POSTS_SUCCESS:
    case GET_POSTS_ERROR:
        return getPostsReducer(state,action)
     
    case GET_POST:
    case GET_POST_SUCCESS:
    case GET_POST_ERROR:
        return getPostReducer(state,action)     

    default:
      return state;
  }
}

야호

profile
개발자 꿈나무
post-custom-banner

0개의 댓글