
목차
Redux Saga
액션을 모니터링하고 있다가 특정 Action 이 발생하면 특정 작업을 진행한다.
- 비동기 작업을 진행할 때 기존 요청을 취소 할 수 있다.
- 특정 Action 이 발생했을 때 다른 액션을 디스패치 하거나 자바스크립트 코드를 실행할 수 있다.
- Generator 에 기반한 미들웨어
Generator
함수의 흐름을 특정 구간에 멈춰 놨다가 다시 실행 할 수 있다.
return 값을 여러번 보낼 수 있다.
import { delay, put, takeEvery, takeLatest } from "redux-saga/effects";
const SET_DIFF = "counter/SET_DIFF"; const INCREASE = "counter/INCREASE"; const DECREASE = "counter/DECREASE"; const INCREASE_ASYNC = "NCREASE_ASYNC"; const DECREASE_ASYNC = "DECREASE_ASYNC";
export const setDiff = (diff) => ({ type: SET_DIFF, diff }); export const increase = () => ({ type: INCREASE }); export const decrease = () => ({ type: DECREASE });
export const increaseAsync = () => ({ type: INCREASE_ASYNC }); export const decreaseAsync = () => ({ type: DECREASE_ASYNC });
function* increaseSaga() { yield delay(1000); yield put(increase()); }
function* decreaseSaga() { yield delay(1000); yield put(decrease()); }
export function* counterSaga() { yield takeEvery(INCREASE_ASYNC, increaseSaga); yield takeLatest(DECREASE_ASYNC, decreaseSaga); }
const initialState = { number: 0, diff: 1, };
export default function counter(state = initialState, action) { switch (action.type) { case SET_DIFF: return { ...state, diff: action.diff, }; case INCREASE: return { ...state, number: state.number + state.diff, }; case DECREASE: return { ...state, number: state.number - state.diff, }; default: return state; } }
|
import React from "react"; import { useSelector, useDispatch } from "react-redux"; import Counter from "./Counter"; import { increase, decrease, setDiff, increaseAsync, decreaseAsync, } from "../modules/counter";
const CounterContainer = () => { const { number, diff } = useSelector((state) => ({ number: state.counter.number, }));
const dispatch = useDispatch(); const onIncrease = () => dispatch(increaseAsync()); const onDecrease = () => dispatch(decreaseAsync()); const onSetDiff = (diff) => dispatch(setDiff(diff));
return ( <Counter number={number} diff={diff} onIncrease={onIncrease} onDecrease={onDecrease} onSetDiff={onSetDiff} /> ); };
export default CounterContainer;
|
import { combineReducers } from "redux"; import counter, { counterSaga } from "./counter"; import todos from "./todos"; import { all } from "redux-saga/effects";
const rootReducer = combineReducers({ counter, todos, });
export function* rootSaga() { yield all([counterSaga()]); }
export default rootReducer;
|
import React from 'react'; import ReactDOM from 'react-dom'; import './index.css'; import App from './App'; import reportWebVitals from './reportWebVitals'; import { createStore, applyMiddleware } from 'redux'; import rootReducer, { rootSaga } from './modules'; import { Provider } from 'react-redux'; import myLogger from './middlewares/myLogger'; import createSagaMiddleware from 'redux-saga';
const sagaMiddleware = createSagaMiddleware(); const store = createStore(rootReducer, applyMiddleware(sagaMiddleware, myLogger));
sagaMiddleware.run(rootSaga);
ReactDOM.render( <Provider store={store}> <App /> </Provider>, document.getElementById('root') );
reportWebVitals();
|