[React Redux] Redux-Saga 사용하기 (Starwars api 활용 테스트)
Redux-Saga 를 세팅한 후 Axios 로 api 를 호출하여 얻은 결과 데이터를 store에 저장하고 뷰 화면에서 가져다 사용해보자.
api 는 직접 만들어서 사용해도 되지만 필자는 SWAPI 라는 곳에 Starwars api 를 테스트에 활용했다.
SWAPI 사이트 주소 : https://swapi.dev/
SWAPI - The Star Wars API
What is this? The Star Wars API, or "swapi" (Swah-pee) is the world's first quantified and programmatically-accessible data source for all the data from the Star Wars canon universe! We've taken all the rich contextual stuff from the universe and formatted
swapi.dev
작업 github 주소 : https://github.com/bumrei/redux-practice-react/tree/redux_saga_axios_use_api
GitHub - bumrei/redux-practice-react: This is the repository for the redux setting and using practice.
This is the repository for the redux setting and using practice. - GitHub - bumrei/redux-practice-react: This is the repository for the redux setting and using practice.
github.com
1.) Redux-Saga 세팅하기
먼저 아래 이미지를 참고하여 saga.js 라는 파일을 만들어준다.
2-1. saga.js 세팅
import { takeEvery } from "redux-saga/effects";
import { SAGA_TEST } from "./actions";
function* loadStartwarsMemberOne(action) {
const {payload} = action;
console.log("saga work >> ", payload)
}
export default function* apiSaga() {
yield takeEvery(SAGA_TEST, loadStartwarsMemberOne)
}
2-2. rootSaga 구성 및 store 에 연결
src/store/index.js
import { combineReducers } from "redux";
import forTheTest from "./reduxTest/reducers";
import multiTest from "./starwarsInfo/reducers";
import apiSaga from "./reduxTest/saga";
import { all } from "redux-saga/effects";
const rootReducer = combineReducers({
forTheTest,
multiTest
})
export function* rootSaga() {
yield all([
apiSaga()
])
}
export default rootReducer;
src/index.js
.
. // 생략
.
const sagaMiddleware = createSagaMiddleware();
const store = configureStore({
reducer: rootReducer,
middleware: [serializableMiddleware, sagaMiddleware],
})
sagaMiddleware.run(rootSaga);
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<Provider store={store}>
<BrowserRouter>
<RouterHome />
</BrowserRouter>
</Provider>
</React.StrictMode>
);
2.) Generator 함수 사용하기
src/store/reduxTest/saga.js
import { call, delay, put, takeEvery } from "redux-saga/effects";
import { SAGA_TEST, sagaTestResult } from "./actions";
function* loadStartwarsMemberOne(action) {
const {payload} = action;
// select : store 에서 데이터 가져옴
// put : action 발생 시킴
yield put({type : 'RESULT_PENDING', payload : {value : true}})
// 다음 yield 실행 전 딜레이 발생시킴
yield delay(500);
yield put({type : 'RESULT_TEST_ONE', payload : {value : payload}});
yield put({type : 'RESULT_PENDING', payload : {value : false}})
}
export default function* apiSaga() {
yield takeEvery(SAGA_TEST, loadStartwarsMemberOne)
}
put 을 통해 action 을 발생시킨다.
src/store/reduxTest/reducers.js
import { SAGA_TEST_RESULT, WRITE_ANY } from "./actions";
const initialState = fromJS({
data1: '',
data2: '',
sagaResult: ''
})
const forTheTest = handleActions(
{
[WRITE_ANY]: (state, action) => {
const {value} = action.payload;
return state.set('data1', value);
},
'RESULT_PENDING': (state, action) => {
const {value} = action.payload;
return state.set('pending', value);
},
'RESULT_TEST_ONE': (state, action) => {
console.log("saga test Reducer 페이지 >> " , action)
const {value} = action.payload;
return state.set('sagaResult', value);
}
},
initialState
);
export default forTheTest;
saga.js 에서 발생된 action 을 reducer에서 받아 특정 로직 처리.
3.) Axios 로 starwars api 호출해보기.
src/store/reduxTest/saga.js
import { call, put, takeEvery } from "redux-saga/effects";
import { SAGA_TEST } from "./actions";
import axios from "axios";
function* loadStartwarsMemberOne(action) {
const {payload} = action;
yield put({type : 'RESULT_PENDING', payload : {value : true}})
try {
// 콜백 함수 호출 및 실행
const result = yield call(() => (
axios.get(`https://swapi.dev/api/people/${payload}/`)
));
const {data} = result;
yield put({type : 'STARWARS_CALL_SUCCESS', payload : {value : data}});
yield put({type : 'RESULT_PENDING', payload : {value : false}})
} catch (error) {
console.log(error.message);
alert("Error Occured!! \n" + error.message);
yield put({type : 'RESULT_PENDING', payload : {value : false}})
}
}
export default function* apiSaga() {
yield takeEvery(SAGA_TEST, loadStartwarsMemberOne)
}
saga.js 에 yield call 및 api 작동 확인
정상 작동 확인.