전에 만든 포스트리스트 컴포넌트의 redux-saga 코드를 리팩토링해서 간결한 코드로 만들어보자
lib/asyncUtils.js 에서 thunk의 리팩토링을 위해 작성한 createPromiseThunk, createPromiseSagaById와 비슷한 방식으로 작성한다. type와 promiseCreator를 파라미터로 사용하고, SUCCESS와 ERROR를 type 값에서 비구조화 할당으로 가져온다.
promiseCreator 값을 yield call 하여 가져온 action.payload 값을 result로 지정했고, SUCCESS의 경우 payload를 result로 설정하고, ERROR의 경우는 error값을 true로 변경하고 payload를 e로 지정한다.
import {call, put} from 'redux-saga/effects'
export const createPromiseSaga = (type, promiseCreator) => {
const [ SUCCESS, ERROR] = [`${type}_SUCCESS`, `${type}_ERROR`];
return function* saga(action) {
try {
const result = yield call(promiseCreator, action.payload);
yield put({
type: SUCCESS,
payload: result
});
} catch(e){
yield put({
type:ERROR,
error: true,
payload: e
})
}
}
}
createPromiseSagaById 도 비슷하게 작성하되 thunk의 리팩토링 경우 id 값을 idSelector를 사용해서 가져왔지만, saga의 경우는 id값을 지정한 meta를 불러오는 방식을 사용한다.
export const createPromiseSagaById = (type, promiseCreator) => {
const [SUCCESS, ERROR] = [`${type}_SUCCESS`, `${type}_ERROR`];
return function* saga(action) {
const id = action.meta;
try {
const result = yield call(promiseCreator, action.payload)
yield put({
type: SUCCESS,
payload: result,
meta: id
});
} catch (e) {
yield put({
type: ERROR,
payload: e,
error: true,
meta: id
});
}
};
}
이렇게 2개의 유틸함수를 제작하면 posts.js 모듈에서 saga 함수 2개를 단 2줄로 표현이 가능해진다.
const getPostsSaga = createPromiseSaga(GET_POSTS, postsAPI.getPosts);
const getPostSaga = createPromiseSagaById(GET_POST, postsAPI.getPostById);