React Middleware

Gisele·2021년 1월 13일
0

Middleware

  • dispatch() 메소드를 통해 store로 가고 있는 액션을 가로채는 코드
  • 비동기 작업이 가능하다
  • 비동기 함수 한개 안에서 여러가지 dispatch 수행이 가능하다

Redux-thunk

  • 리덕스에서 비동기 작업을 처리할 때 가장 많이 사용하는 미들웨어
  • 액션 객체가 아닌 함수를 디스패치 할 수 있다
  • thunk는 액션 생성함수를 만들어 준다 = 함수를 디스패치 할 때는, 해당 함수에서 dispatchgetState를 파라미터로 받아와야하는데, thunk가 이 함수를 만들어준다
  • thunk를 사용하면 액션 생성자는 필요한 값을 파라미터로 받아 함수를 리턴할 수 있음
  • 액션생성함수는 type과 payload가 담긴 객체를 생성해 반환하는 역할을 수행하기로 했는데, thunk 미들웨어에서는 API요청이나 비동기처리까지 하므로 본래의 역할이 모호해짐.

$ npm i redux-thunk

function createThunkMiddleware(extraArgument){
  return ({dispatch,getState})=> (next) => (action) => {
  	if(typeof action === 'function'){
    	return action(dispatch, getState, extraArgument)
    }
    
    return next(action);
  }
}

const thunk = createThunkMiddleware()
thunk.withExtraArgument = createThunkMiddleware;

export default thunk;

Redux-saga

  • 액션에 대한 리스너
  • thunk는 함수나 객체를 반환하는데 반해, saga는 객체만 반환
  • ES6의 generator 문법을 사용한다
  • thunk보다 더 많은 기능을 제공한다

사용법

$ npm i redux-saga
const sagaMiddleware = createSagaMiddleware();
...
composeWithDevTools(applyMiddleware(sagaMiddleware))
...
sagaMiddleware.run(rootSaga)

saga 모듈화

// sagas/index.js -- rootsaga
import {all, fork} from 'redux-saga/effects'
import postSaga from './post'
import userSaga from './user'

export default function * rootSaga(){
    yield all([
        fork(userSaga),
        fork(postSaga)
    ])
}
// sagas/user.js
import {all,fork} from 'redux-saga'

function* logIn(){
    try{
        //const result = yield call(loginAPI)        
        yield put({
            type:'LOG_IN_SUCCSS',
            data:result.data
        })
    }catch(err){
        yield put({
            type:'LOG_IN_FAILURE',
            data:err.response.data
        });
    }    
}
function loginAPI(){
    return axios.post('/api/login')
}

function* logOut(){
    try {
        const result = yield call(login)
        
    } catch (error) {
        
    }
}


function* watchLogin(){
    yield take('LOG_IN_REQUEST',logIn);
}
function* watchLogout(){
    yield take('LOG_OUT_REQUEST');
}

export default function* userSaga(){
    yield all([
        fork(watchLogIn),
        fork(watchLogOut)        
    ])
}

saga-effect

import {all, call, fork, put, take} from 'redux-saga/effects'

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

function* logIn(){
    try{
        const result = yield call(loginAPI)
        yield put({
            type:'LOG_IN_SUCCSS',
            data:result.data
        })
    }catch(err){
        yield put({
            type:'LOG_IN_FAILURE',
            data:err.response.data
        });
    }
    
}

function* watchLogin(){
    yield take('LOG_IN',logIn);
}

function* watchLogout(){
    yield take('LOG_OUT');
}

function* watchAddPost(){
    yield take('ADD_POST')
}

export default function * rootSaga(){
    yield all([
        call(watchLogin), //fork
        call(watchLogout),
        call(watchAddPost),
    ])
}

put

  • 액션을 호출하는 dispatch()의 역할을 수행

call

  • Function.prototype.call()과 같다
  • 동기 함수 호출
  • call로 api 호출을 한 경우 응답이 올때까지 기다림

fork

  • 비동기 함수 호출
  • 응답이 오기 전에 다음 스텝 실행

take

  • 액션을 한 번만 실행

takeEvery

  • 모든 액션마다 실행
  • take는 딱 한번만 동작하므로 while문으로 감싸야하는데, 그것을 대체

takeLatest

  • 액션 호출시에 같은 액션이 실행 중이면 그 액션은 파기되고 마지막 호출만 실행함.
  • 요청이 아닌 응답을 취소함
  • POST, PUT, DELETE 같은 리소스 변경 메서드에 사용

delay

  • 호출을 지연시킴 setTimeout과 같은 역할

throttle

  • 마지막 함수가 호출된 후 일정 시간이 지나기 전에 다시 호출되지 않도록 하는 것

debouncing

  • 연이어 호출되는 함수들 중 마지막 함수(또는 제일 처음)만 호출되도고 하는 것

📑 reference

profile
한약은 거들뿐

0개의 댓글