React로 SNS 만들기 (4) - redux-middleware

SangBooom·2021년 4월 30일
0

react-nodebird

목록 보기
4/7

redux-middleware

리덕스에 없던 기능들을 추가해주는 역할
기존의 컴포넌트에 생기는 사이드이펙트를 최소화함 (기존의 컴포넌트 안에서 했던 비동기 처리를 리덕스에서 하도록 하니까 당연한 말임)

redux-thunk

리덕스가 비동기 액션을 디스패치 할 수 있도록 도와주는 역할
하나의 액션에서 디스패치를 여러번 할 수 있게 해주는 역할
이정도가 redux-thunk의 기능 끝이다. 간단하다.

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

redux-saga

thunk보다 많은 기능들을 제공한다.

제너레이터함수로 rootSaga를 하나 만들고 그안에 넣고싶은 비동기 액션들을 넣는다.
redux-saga의 이펙트들로 all, fork, call, put 등이 있다.

요청이 항상 성공하는것은 아니기 때문에 try catch 문을 쓰는게 좋다.

성공 결과는 (result).data, 실패 결과는 (err).response.data 에 담겨있다.

* , yeild

제너레이터 함수 안에 yield로 함수실행의 중단점을 만들어 낼 수 있다.
yield는 await과 같은 역할?인듯하다.

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

const generator = gen();

generator
// gen {<suspended>}
generator.next()
// 1
// {value: undefined, done: false}
generator.next()
// 2
// {value: undefined, done: false}
generator.next()
// 3
// {value: 4, done: false}
generator.next()
// {value: undefined, done: true}

all

동시에 실행할 수 있도록 등록

take

한번 기다리겠다. (이벤트 리스너같은 역할)

function* watchLogIn() {
  yield take("LOG_IN_REQUEST", logIn);
}

이런식이면 로그인이 한번 되고 나서 다시 로그인이 되지 않는다.

어떻게 해결 해야할까?

방법 1. while

function* watchLogIn() {
  while (true) {
    yield take("LOG_IN_REQUEST", logIn);
  }
}

방법 2. takeEvery

function* watchLogIn() {
  yield takeEvery("LOG_IN_REQUEST", logIn);
}

둘의 차이는 while take는 동기적 동작, takeEvery는 비동기로 동작이라는 점이다.

takeLatest

로그인하기를 여러번 클릭하면 thunk는 요청이 여러번 간다.
하지만 saga는 takeLatest()라는 기능이 제공돼서 가장 마지막 것만 요청을 보낸다.

put

액션을 디스패치

fork

비동기 함수 호출, (결과값을 받아오던말던 그냥 다음줄로 넘어간다.)

call

동기 함수 호출, (결과값을 받을때까지 기다렸다가 다음줄로 넘어간다.)

fork와 call의 차이

아래와 같은 경우

function loginAPI() {
    return axios.post('/api/login')
}

function* login(){
    try {
        const result = yield call(loginAPI)
        yield put({
            type: 'LOG_IN_SUCCESS',
            data: result.data
        })
    } catch (error) {
        yield put({
            type: 'LOG_IN_FAILURE',
            data: error.response.data
        })
    }
}

fork일 경우로 바꾸면 (그러니까 결국 아래와 같은 상황에선 fork를 안쓴다.)

function* login(){
    try {
      axios.post('/api/login')
      yield put({
        type: 'LOG_IN_SUCCESS',
        data: result.data
      })
    } catch (error) {
        yield put({
          type: 'LOG_IN_FAILURE',
          data: error.response.data
        })
    }
}

call일 경우로 바꾸면

function* login(){
    try {
      const result = yield call(loginAPI)
      .then(() => {
        yield put({
          type: 'LOG_IN_SUCCESS',
          data: result.data
        })
      })
    } catch (error) {
        yield put({
          type: 'LOG_IN_FAILURE',
          data: error.response.data
        })
    }
}

생각해보기

불변성을 안지키려면 splice, 유지하려면 filter?
불변성을 유지해야되는 이유?

profile
끊임없이 떨어지는 물방울이 바위를 뚫는다

0개의 댓글