Front-End

vsoghlv@naver.com

React.js 타입스크립트에서 redux Saga 사용2 리팩토링

이전에 작성했던 saga 를 조금 더 쉽게 사용하기 위해 유틸함수를 만들어보자.

//lib/createAsyncSaga.ts
//P = promiseCreator 호출 할 때 넣는 파라미터, T = 해당 promiseCreator 만든 promise 에서 내보내는 결과값

import { call, put } from "redux-saga/effects";
import { AsyncActionCreatorBuilder, PayloadAction } from "typesafe-actions";

//파라미터가 없는 경우도 작동할 수 있도록 or 로 처리
type PromiseCreatorFunction<P, T> =
  | ((payload: P) => Promise<T>)
  | (() => Promise<T>);

//타입가드 문법
//액션.payload 가 undefinde 가 아니라면  파라미터로 받아온 액션은 payload 액션타입이다.
function isPayloadAction(action: any): action is PayloadAction<string, any> {
  return action.payload !== undefined;
}

export default function createAsyncSaga<T1, P1, T2, P2, T3, P3>(
  asyncActionCreator: AsyncActionCreatorBuilder<
    // [액션타입 , 페이로드타입] or [액션타입 [페이로드타입,메타타입]]
    [T1, [P1, undefined]],
    [T2, [P2, undefined]],
    [T3, [P3, undefined]]
  >,
  promiseCreator: PromiseCreatorFunction<P1, P2>
) {
  return function* saga(action: ReturnType<typeof asyncActionCreator.request>) {
    try {
      //isPayloadAction 이 true 인 경우와 아닌 경우
      const result: P2 = isPayloadAction(action)
        ? yield call(promiseCreator, action.payload)
        : yield call(promiseCreator);
      yield put(asyncActionCreator.success(result));
    } catch (e) {
      yield put(asyncActionCreator.failure(e));
    }
  };
}

//modules/github/saga.ts
import { getUserProfileAsync, GET_USER_PROFILE } from "./actions";
//call = 특정 함수 호출, put = 액션 디스패치, takeEvery = 특정액션 모니터링 중 원하는 액션 들어올 시 정해놓은 사가함수 호출
import { takeEvery } from "redux-saga/effects";
import { getUserPeofile } from "../../api/guthub";
import createAsyncSaga from "../../lib/createAsyncSaga";

// function* getUserProfileSaga(
//   action: ReturnType<typeof getUserProfileAsync.request>
// ) {
//   try {
//     const userProfile: GithubProfile = yield call(
//       getUserPeofile,
//       action.payload
//     );
//     //성공시
//     yield put(getUserProfileAsync.success(userProfile));
//   } catch (e) {
//     //실패시
//     yield put(getUserProfileAsync.failure(e));
//   }
// }

const getUserProfileSaga = createAsyncSaga(getUserProfileAsync, getUserPeofile);

export function* githubSage() {
  //GET_USER_PROFILE 액션 감지시 사가함수 호출
  yield takeEvery(GET_USER_PROFILE, getUserProfileSaga);
}