[Redux] 미들웨어 Redux-Saga

김지민·2023년 3월 9일
0

Redux

목록 보기
1/2
post-thumbnail

왜 Redux Saga or thunk를 이용하게 되었는가?

바로 Redux의 비동기 처리를 위함이다!

세개가 삼박자로 조금 복잡하게 돌아간다!

  • reducer => store 안에 있는 state를 바꾸는 방법, 현재의 state + action -> new state
  • dispatch => state 업데이트를 위한 요구
  • action => 요구의 내용
import {createStore} from 'redux';
import {Provider, useSelector, useDispatch } from 'react-redux';

function reducer(currentState, action) {
      if (currentState === undefined) {
         return {
             number: 1,
         };
       }
      const newState = {...currentState};
      if (action.type === "PLUS") {
          newState.number ++;
      }
      return new State    
   }

const store = createStore(reducer);

새로운 component

function Left3() {
   const dispatch = useDispatch();
   const number = useSelector((state) => state.number);
     return (
       <div>number</div>
       <input onClick = {() => { dispatch({type: "PLUS"});} ></input> // dispatch 가 일어나면 reducer가 호출된다.

   );
}

Redux thunk

코드가 간단하다.
하지만 다양한 기능을 가지고 있지 않는다.(delay 기능)

export const loginAction = (data) => {
    return (dispatch, getState) => {
       const state = getState();
       dispatch(loginRequestAction());
       axios.post('/api/login')
         .then(()=> {
            dispatch(loginSuccessAction());
         })
         .catch(() => {
             dispatch(loginFailureAction());
         })
     }
}

export const loginRequestAction = (data) => {
     return {
        type: 'LOG_IN_RQUEST',
        data,
     }
};

thunk 대신 saga를 사용하는 이유

실수로 클릭을 두번하거나, thunk 2번의 클릭에 요청이 모두 간다.
하지만 saga의 경우는 마지막 경우만 진행
스크롤 이벤트를 1초에 수백번 일어난다.
하지만, 그때 비동기 통신을 걸어두면 서버에 요청이 수백개 날아간다.
이때 DDOS 공격이 생길 수 있다.
프론트 실력과 연관될 수 있다.

공포의 saga 문법

어려운 이유는 제너레이터를 사용하기 때문이다.

const gen = function* () {
   console.log(1);
   yield;
   console.log(2);
   yield;
   console.log(3);
   yield;
}
const generate = gen();
generate.next()
//1

generate.next()
//2

generate.next()
//3

제너레이터는 yield를 기준으로 중단점이 있는 함수이다.

export default function* rootSaga() {

}

saga effect

루트 사가를 만든 후 그 곳에 만들고 싶은 비동기 action을 만들어 준다.

  • all : 배열 안에 있는 것들을 동시에 실행 시켜준다.
  • fork : 함수를 실행한다.
  • put: dispatch
  • takeLatest: 마지막 같은 액션이 연달아 진행 된다면 앞선 응답에 대해서는 취소한다. 요청은 2번 응답은 1번
  • throttle: 요청도 제한을 두어서 한번만 진행 되도록 한다.
import { all, fork, take, call, put } from "redux-saga/effects";
import axios from "axios";

function logInAPI() {
  return axios.post("/api/login");
}

// 서버에게 요청하는 함수인 login 함수 실
function* logIn() {
  try {
    const result = yield call(logInAPI);
    yield put({
      type: "LOG_IN_SUCEESS",
      data: result.data,
    });
  } catch (err) {
    yield put({
      type: "LOG_IN_FAILURE",
      data: err.response.data,
    });
  }
}

//"LOG_IN"이라는 액션이 실행될 때까지 기다리겠다. 이후 로그인 제너레이처 함수를 실행를 실행 시키겠다.
// 이벤트 리슨어 처럼 실행된다.
function* watchLogin() {
  yield take("LOG_IN_REQUEST", login);
}


// rootsaga
// watchLogin fork 실행 watchLogout fork 실행
// event listener 등록
export default function* rootSaga() {
  yield all([fork(watchLogin), fork(watchLogout), fork(watchAddpost)]);
}

call과 fork의 차이

  • fork: 비동기
  • call: 동기

saga effect를 사용하는 이유

단순 프로그램을 동작하기 위함이 아니다.
동작이 제대로 돌아가고 있는지 보장을 받는게 중요하다.
때문에 effect를 사용해서 테스트를 사용하면 프로그램 동작을 확인하기가 쉽다.

profile
💡Habit is a second nature. [Git] https://github.com/Kimjimin97

0개의 댓글