본문 바로가기

개발/React.js

[React.js] Redux-thunk란? && Custom Middleware

What is "Redux-thunk"

공식 문서에 나와 있는 설명 한 문장

Thunk middleware for Redux.

It allows writing functions with logic inside that can interact

with a Redux store's dispatch and getState methods.

 

Redux를 위한 멋진 미들웨어입니다.
그것은 상호 작용할 수 있는 논리 내부의 쓰기 기능을 허용합니다.
Redux의 DispatchgetState 메서드를 사용합니다.

 

+

Redux-thunk와 Redux-saga는 둘 다 Redux의 미들웨어 라이브러리입니다.

Redux 미들웨어는 dispatch()메소드를 통해

store로 가고 있는 액션을 가로채는 코드입니다.

 


 

쉽게 말해 '지연된 함수'를 뜻한다.

 

const INCREMENT_COUNTER = 'INCREMENT_COUNTER'

function increment() {
  return {
    type: INCREMENT_COUNTER
  }
}

function incrementAsync() {
  return dispatch => {
    setTimeout(() => {
      // Yay! Can invoke sync or async actions with `dispatch`
      dispatch(increment())
    }, 1000)
  }
}

 

increment()는 sync(동기) action creator 함수인데,

이 함수를 async(비동기)로 함수를 쓸 수 있다. ( incrementAsync() )

즉, 함수를 호출할 때 dispatch가 된다.

 

 

이렇게 구현하면

 

장점

 

1. 1개의 액션에서

Dispatch를 여러번 할 수 있다.

 

가령, axios 요청을 보낼 때

request action을 dispatch

load action success를 dispatch

등등등....

여러번 dispatch를 할 수 있다.

Redux 기능이 확장된다고 보면 된다.

 

 

 


 

 

사실, 이 react-thunk 내부의 코드를 살펴보면

몇 줄 되지도 않는다. 

그런데, 17.4k의 Star를 받고 있다.

 

import type { Action, AnyAction } from 'redux'

import type { ThunkMiddleware } from './types'

export type {
  ThunkAction,
  ThunkDispatch,
  ThunkActionDispatch,
  ThunkMiddleware
} from './types'

/** A function that accepts a potential "extra argument" value to be injected later,
 * and returns an instance of the thunk middleware that uses that value
 */
function createThunkMiddleware<
  State = any,
  BasicAction extends Action = AnyAction,
  ExtraThunkArg = undefined
>(extraArgument?: ExtraThunkArg) {
  // Standard Redux middleware definition pattern:
  // See: https://redux.js.org/tutorials/fundamentals/part-4-store#writing-custom-middleware
  const middleware: ThunkMiddleware<State, BasicAction, ExtraThunkArg> =
    ({ dispatch, getState }) =>
    next =>
    action => {
      // The thunk middleware looks for any functions that were passed to `store.dispatch`.
      // If this "action" is really a function, call it and return the result.
      if (typeof action === 'function') {
        // Inject the store's `dispatch` and `getState` methods, as well as any "extra arg"
        return action(dispatch, getState, extraArgument)
      }

      // Otherwise, pass the action down the middleware chain as usual
      return next(action)
    }
  return middleware
}

const thunk = createThunkMiddleware() as ThunkMiddleware & {
  withExtraArgument<
    ExtraThunkArg,
    State = any,
    BasicAction extends Action = AnyAction
  >(
    extraArgument: ExtraThunkArg
  ): ThunkMiddleware<State, BasicAction, ExtraThunkArg>
}

// Attach the factory function so users can create a customized version
// with whatever "extra arg" they want to inject into their thunks
thunk.withExtraArgument = createThunkMiddleware

export default thunk

 

dispatch를 한 방에 묶어서 할 수 있게 해주는 것이

react-thunk의 역할이다.

 

 


 

그럼 여기서 사용하고 있는

Middleware가 도대체 무엇인가?

 

- 3단 함수로 되어 있다.

 

이 Middleware를 Custom하여 사용할 수도 있다.

위의 코드의 일부를 가져와보자.

 

// Action을 하기 전에 Console을 한 번 찍어주는 Middleware Custom
const loggerMiddleware = ({ dispatch, getState }) => (next) => (action) => {
      console.log(action);
      return next(action);
};

- action을 Function으로 둘 수 있다.

- 인자로 받은 next, action, dispatch를 이용하여 조작을 할 수 있다.

 


 

출처 - Zerocho님 강의 및 redux-thunk 공식 문서