본문 바로가기

React.JS

redux-thunk 알아보기

리덕스의 비동기 처리 라이브러리 중 하나인 redux-thunk에 대해서 알아보겠습니다.

비동기 라이브러리는 주로 action이 dispatch 되어 reducer에서 state수정이 일어나기 전 무언가 다른 처리를 해주기 위해 사용합니다. 대표적으로 ajax요청이 있습니다.

redux-thunk는 이를 위한 방법으로 액션 생성자가 함수를 리턴하였을 경우 함수 내에 dispatch를 인자로 전달해주는 방법을 사용합니다. 액션 생성자가 리턴한 함수 내에 비동기 요청이나 로직을 저장해 두고 이를 원하는 조건이나 시기에 비동기적으로 활용할 수 있게 되는 것입니다. 기존에는 액션 생성자가 액션 객체를 리턴하면 바로 dispatch 되어 리듀서에서 스테이트 수정이 일어났습니다. 하지만, 액션 생성자가 함수를 리턴하게 되면 redux-thunk에서 액션 함수에 dispatch 함수를 파라미터로 전달해주고 함수 내에서 비동기 처리를 한 후 dispatch를 할 수 있게  되는 것입니다.

redux-thunk의 소스코드는 매우 단순합니다. 아래의 코드가 끝입니다. 액션이 함수일 경우 action함수를 실행하고, 아닐 경우 action을 다음 미들웨어로 보내거나 reducer로 디스패치 합니다.

// redux-thunk 소스코드
function createThunkMiddleware(extraArgument) {
// applyMiddleware에서 store.dispatch, store.getState, next, action을 고차함수형태로 접근가능하게 해줌
	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;

아래는 액션 생성자가 함수를 리턴하는 예시 코드입니다. 비동기적으로 1초 뒤에 dispatch가 됩니다.

// 객체를 리턴하는 액션생성함수
export const increment = () => ({ type: INCREMENT });
// 함수를 리턴하는 액션생성함수
export function incrementAsync() {
  return function (dispatch) { // 여기의 dispatch는 redux-thunk에서 넣어준다.
    setTimeout(() => {
      dispatch(increment());
    }, 1000);
  };

 

// 컴포넌트

const handleOnIncrement = () => {
    dispatch(incrementAsync()); 
 };

 

즉 정리하자면 다음과 같습니다. 

  1. 액션 생성자에서 함수가 리턴됨 
  2. 리턴된 함수를 필요한 컴포넌트에서 dispatch 함 
  3. disaptch 했더니 action이 객체가 아니라 함수인 것을 redux-thunk 미들웨어에서 발견
  4.  redux-thunk에서 액션 함수를 실행할 때 dispatch를 넣어줌
  5. 드디어 액션함수를 실행함
  6. thunk에서 받아온 dispatch함수로 액션 객체를 dispatch 함