React

React-Thunk를 활용한 비동기적 상태관리

학습했던 내용을 정리하기 위해 작성된 글이며 다소 부정확한 내용이 포함될 수 있음을 양해바랍니다.

이미 게시된 글이라도 복습하는 과정에서 내용이 보완 또는 수정될 수 있습니다.

 

 

리덕스는 기본적으로 동기적인 상태 업데이트를 수행한다. 만약 비동기적으로 상태를 업데이트해야 한다면, redux-thunk라는 미들웨어를 사용할 수 있다. thunk를 사용하면 액션 크리에이터가 액션을 리턴하는 대신 함수를 리턴할 수 있다. thunk가 action creator에 직접 개입하는 것은 아니다. 리듀서가 순수한 액션 객체를 인수로 받는 것과 달리, 미들웨어는 특정한 액션(여기서는 함수를 리턴하는 액션)을 인식하여 커스텀된 로직을 실행한다. 즉 미들웨어를 통해 커스텀 된 dispatch를 실행할 수 있다. 그래서 특정 액션이 실행되는 것을 지연시키거나 특정한 조건이 충족될 때 액션이 실행될 수 있도록 한다.

 

//store.js

import { applyMiddleware, createStore } from 'redux';

import thunk from 'redux-thunk';

import reducer from './reducer';

const store = createStore(reducer, applyMiddleware(thunk));

export default store;

미들웨어를 사용하기 위해서는 applyMiddleware를 import, 그리고 위 코드처럼 thunk를 적용시킨다.

 

//App.jsx
//Thunk를 사용하지 않는 경우

import { useEffect } from 'react';

import { useDispatch } from 'react-redux';

import { fetchRegions } from './api';

import { updateRegions } from '../actions';

async function loadRegions() {
	const url = 'https://blabla.com';
	const data = await fetchRegions();
	dispatch(updateRegions(data));
}

export default function App() {
	const dispatch = useDispatch();
	
	useEffect(() => {
		loadRegions();
  }, []);

	return (
    <div>
      ...
    </div>
  );
}

useEffect, fetch를 통해 초기 데이터를 불러오기 위해서는 컴포넌트에서 비동기적 코드를 작성해야 한다. fetch를 분리시켜 주었음에도 앱의 규모에 따라 로직이 복잡해질 가능성이 다분해 보인다.

 

만약 thunk를 사용한다면 코드가 더 간결해질 수 있다.

//App.jsx
//Thunk를 사용한다면?

import { useEffect } from 'react';

import { useDispatch } from 'react-redux';

import { loadRegions } from '../actions';

export default function App() {
	const dispatch = useDispatch();
	
	useEffect(() => {
		dispatch(loadRegions());
  }, []);

	return (
    <div>
      ...
    </div>
  );
}

컴포넌트가 더 이상 비동기적 함수를 포함하지 않아도 된다. 대신 thunk로 작성된 action creator를 dispath한다. 

 

//actions.js

import { fetchRegions } from './api';

export function updateRegions(regions) {
  return {
    type: 'updateRegions',
    payload: {
      regions,
    },
  };
}

export function loadRegions() {
  return async (dispatch) => {
    const regions = await fetchRegions();
    dispatch(updateRegions(regions));
  };
}

여기서 loadRegions는 일반적인 action creator가 아니다. 액션 객체를 리턴하지 않기 때문이다. loadRegions는 thunk에 의해 dispath, getState(optional) 메서드를 인수로 받는 함수를 리턴할 수 있다. loadRegions는 fetch 함수를 통해 데이터를 전달받아 다른 액션을 디스패치한다. 비동기적 프로세스로 다른 액션을 디스패치할 수 있는 함수인 셈이다.

'React' 카테고리의 다른 글

React defaultProps  (0) 2022.01.24
의존성 주입이란 무엇인가?  (0) 2021.09.19
React-Redux 저장소(Store) 생성하기  (0) 2021.09.10
Flux와 MVC의 차이에 대해 공부하기  (0) 2021.08.30