redux비동기처리3(redux-promise)

Jul 8th 2021 by jyoon

아래 github에 redux-promise로 처리한 비동기처리 코드를 확인/동작을 확인 할 수 있다.

redux-promise란?

  • redux비동기처리2(redux-thunk) 게시글에서 thunk는 비동기 시작, 성공, 실패에 대한 actions creator를 직접 입력해야 하지만
  • promise-redux는 비동기 작업을 처리하는 action 타입에 post fix를 붙여 (PENDING,FULLFILLED, _REJECTED)

    • promise의 비동기 처리 성공, 실패에 따라서 자동으로 dispatch 해준다.
    • 그래서 reducer에서 다음과 같이 세가지 타입에 대한 reducer를 작성해줘야한다.
    • [action type]PENDING, [action type]FULLFILLED, [action type]_REJECTED

redux-promise 동작 원리

  • 어떤 타입으로 dispatch 할때 payload에 promise 함수가 있으면

    • 어떤 타입에 PENDING,FULFILLED, _REJECTED를 붙인 action type이 생성된다.
  • payload에 promise 함수가 성공, 실패 여부에 따라서

    • 성공하면 [type]_FULFILLED 액션으로 payload 프로퍼티로 설정한 promise함수의 return 값을 reducer로 넘긴다.
    • 실패하면 [type]_REJECTED 액션으로 payload 프로퍼티로 promise의 error값을 reducer로 넘긴다.

redux-promise 정리

  • thunk는 비동기 시작, 성공, 실패에 대한 actions creator를 직접 입력해야 하지만
  • promise-redux는 비동기 작업을 처리하는 타입에 post fix를 붙여 (PENDING,FULLFILLED, _REJECTED)
  • promise의 비동기 처리 성공, 실패에 따라서 자동으로 dispatch 해준다.

예제 코드

  • 설정4에서 actions create "getUsersPromise"를 통해서 redux-promise를 통해서 비동기 처리가 수행됩니다.
  • 그리고는 설정2 -> 설정3을 통해서 reudx-promise를 통한 비동기 처리가 수행됩니다.

설정1

  • redux-promise 미들웨어 설정

    import { applyMiddleware, createStore } from 'redux';
    import reducer from './reducers/reducer';
    import { composeWithDevTools } from 'redux-devtools-extension';
    import thunk from 'redux-thunk';
    import promise from 'redux-promise-middleware';
    
    
    const store = createStore(
    reducer,
    composeWithDevTools(
      applyMiddleware(promise),
    ),
    );
    
    export default store;

설정2

  • action creator 설정

    • payload의 promise 객체의 결과에 따라서 reducer로 자동 dispatch 해준다.
    • 그래서 다음 세가지 타입에 대해서 reducer에 대해서 작성해야 한다.(GETUSERSPENDING, GETUSERSFULFILLED, GETUSERSREJECTED)
    //src/redux/actions.js
    import axios from 'axios';
    
    const GET_USERS = 'GET_USERS';
    
    export const GET_USERS_PENDING = 'GET_USERS_PENDING';
    export const GET_USERS_FULFILLED = 'GET_USERS_FULFILLED';
    export const GET_USERS_REJECTED = 'GET_USERS_REJECTED';
    
    export function getUsersPromise() {
    return {
      type: GET_USERS,
      payload: async () => {
        const res = await axios.get('https://api.github.com/users');
        return res.data;
      },
    };
    }

설정3

  • reducer 설정
  • 설정2에서 설정한 actions creator(getusersPromise)의 payload promise 객체의 결과에 따라서
  • redux-promise 미들웨어가 reducer를 자동 호출해 다음 세가지 타입에 따라서 처리된다.

    • "GETUSERSPENDING, GETUSERSFULFILLED, GETUSERSREJECTED"
    import {
    GET_USERS_PENDING,
    GET_USERS_FULFILLED,
    GET_USERS_REJECTED,
    } from '../actions';
    
    const initialState = {
    loading: false,
    data: [],
    error: null,
    };
    
    export default function user(state = initialState, action) {
    // redux-thunk reducer 처리
    
    // redux-promise reducer 처리
    if (action.type === GET_USERS_PENDING) {
      return {
        ...state,
        laoding: true,
        error: null,
      };
    }
    if (action.type === GET_USERS_FULFILLED) {
      return {
        ...state,
        laoding: false,
        data: action.payload,
      };
    }
    if (action.type === GET_USERS_REJECTED) {
      return {
        ...state,
        laoding: false,
        error: action.payload,
      };
    }
    return state;
    }

설정4

  • component 에서 creator actions을 dispatch
  • actions create "getUsersPromise"를 통해서 redux-promise를 통해서 비동기 처리가 수행됩니다.

    import axios from 'axios';
    import { useCallback } from 'react';
    import { useDispatch, useSelector } from 'react-redux';
    import UserList from '../components/UserList';
    import {
    getUsersPromise,
    } from '../redux/actions';
    
    export default function UserListContainer() {
    const users = useSelector((state) => state.users.data);
    const dispatch = useDispatch();
    
    const getUsers = useCallback(() => {
      dispatch(getUsersPromise()); // redux-promise 방법
    }, [dispatch]);
    
    return <UserList users={users} getUsers={getUsers} />;
    }