728x90
1. redux-saga
1. 3 API 요청 상태 관리하기
이번에는 redux-saga를 사용하여 API 요청을 해 보겠습니다. 기존에 thunk로 관리하던 액션 생성 함수를 제거하고, saga를 사용하여 처리합니다.
sample 리덕스 모듈을 아래와 같이 수정합니다.
- modules/sample.js
import { createAction, handleActions } from "redux-actions";
import { call, put, takeLatest } from "redux-saga/effects";
import * as api from "../lib/api";
import { startLoading, finishLoading } from "./loading";
// 액션 타입을 선언합니다.
const GET_POST = "sample/GET_POST";
const GET_POST_SUCCESS = "sample/GET_POST_SUCCESS";
const GET_POST_FAILURE = "sample/GET_POST_FAILURE";
const GET_USERS = "sample/GET_USERS";
const GET_USERS_SUCCESS = "sample/GET_USERS_SUCCESS";
const GET_USERS_FAILURE = "sample/GET_USERS_FAILURE";
export const getPost = createAction(GET_POST, (id) => id);
export const getUsers = createAction(GET_USERS);
function* getPostSaga(action) {
yield put(startLoading(GET_POST)); // 로딩 시작
// 파라미터로 actions를 받아오면 액션 정보를 조회할 수 있음
try {
// call을 사용하면 Promise를 반환하는 함수를 호출하고, 기다릴 수 있음
// 첫 번쨰 파라미터는 함수, 나머지 파라미터는 해당 함수에 넣을 인수
const post = yield call(api.getPost, action.payload);
yield put({
type: GET_POST_SUCCESS,
payload: post.data,
});
} catch (e) {
yield put({
type: GET_POST_FAILURE,
payload: e,
error: true,
});
}
yield put(finishLoading(GET_POST));
}
function* getUserSaga() {
yield put(startLoading(GET_USERS)); // 로딩 시작
try {
const users = yield call(api.getUsers);
yield put({
type: GET_USERS_SUCCESS,
payload: users.data,
});
} catch (e) {
yield put({
type: GET_USERS_FAILURE,
payload: e,
error: true,
});
}
yield put(finishLoading(GET_USERS));
}
export function* sampleSaga() {
yield takeLatest(GET_POST, getPostSaga);
yield takeLatest(GET_USERS, getUserSaga);
}
// 초기 상태를 선언합니다.
// 요청의 로딩 중 상태는 loading이라는 객체에 관리합니다.
const initialState = {
post: null,
users: null,
};
const sample = handleActions(
{
[GET_POST_SUCCESS]: (state, action) => ({
...state,
post: action.payload,
}),
[GET_USERS_SUCCESS]: (state, action) => ({
...state,
users: action.payload,
}),
},
initialState
);
export default sample;
여기서 GET_POST 의 경우 API를 요청할 떄 어떤 id로 조회할지 정해줄 필요가 있습니다.
redux-saga를 사용할 떄는 id처럼 요청에 필요한 값을 액션의 payload값으로 넣어 주어야 합니다.
API를 호출해야하는 상황에는 Saga 내부에서 직접 호출하지 않고 call 함수를 사용합니다.
call 함수는 첫번쨰 인자는 호출하고싶은 함수를 선택하고, 그뒤에 인자들은 해당 함수에 넣어주고 싶은 값들을 의미힙니다.
getPostSaga의 경우 id를 의미하는 action.payload가 이에 해당합니다.
이제 sampleSaga를 루트 사가에 등록 하겠습니다.
- modules/index.js
import { combineReducers } from "redux";
import { all } from "redux-saga/effects";
import counter, { counterSaga } from "./counter";
import sample, { sampleSaga } from "./sample";
import loading from "./loading";
// 루트 리듀서 작성
const rootReducer = combineReducers({
counter,
sample,
loading,
});
export function* roottSaga() {
yield all([counterSaga(), sampleSaga()]);
}
export default rootReducer;
루트 Saga를 등록했으니 이제 App.js에서 SampleContaine를 렌더링 해주세요
- App.js
import React from "react";
import SampleContainer from "./containers/SampleContainer";
const App = () => {
return (
<div>
<SampleContainer />
</div>
);
};
export default App;
이제 기능이 정상적으로 동작하는지 redux 탭에서 확인해 보세요.
728x90
'프론트엔드 > React' 카테고리의 다른 글
[프론트엔드] 코드 스플리팅 [1] (0) | 2022.06.05 |
---|---|
[프론트엔드] 리덕스 미들웨어를 통한 비동기 작업 관리[10] (0) | 2022.06.03 |
[프론트엔드] 리덕스 미들웨어를 통한 비동기 작업 관리[8] (0) | 2022.06.02 |
[프론트엔드] 리덕스 미들웨어를 통한 비동기 작업 관리[7] (0) | 2022.05.01 |
[프론트엔드] 리덕스 미들웨어를 통한 비동기 작업 관리[6] (0) | 2022.04.27 |