React/Redux - React

[React Redux] Redux-Saga 사용하기 (Starwars api 활용 테스트)

Denny Code 2023. 8. 13. 19:08

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 작동 확인

 

 

정상 작동 확인.