React
[React] redux-thunk로 비동기 동작 다루기 + 예제
fnow
2024. 2. 4. 17:58
반응형
Redux Thunk는 미들웨어 중 하나로, 비동기 작업을 처리하고 액션을 디스패치할 수 있게 도와주는 라이브러리다. 리덕스는 동기적인 작업에 특화되어 있어서, 비동기 작업을 처리하기 위해서는 Thunk와 같은 미들웨어가 필요하다. 그 외에도 비동기 작업을 처리하는 미들웨어로 Redux Saga, Redux Observable 등이 있다.
동기적 액션 생성자와 Thunk를 사용한 비동기 액션 생성자 비교
동기적 액션 생성자
- 액션 함수는 단순히 액션 ‘객체’를 반환
- 반환 형식:
{ type: '액션_타입', payload: '데이터' }
- 동기적인 액션을 생성하는 역할
Thunk를 사용한 비동기 액션 생성자
- 비동기 액션 함수는 ‘함수’를 반환
- 비동기 액션 함수는
dispatch
를 인자로 받음
이를 통해 함수 내부에서 다른 액션을 디스패치할 수 있는 권한을 갖게 되는 것 - 비동기 코드 실행 전, 실행 후 등 비동기 동작 전 후 상황에서 액션을 실행해야 할 때 디스패치를 사용
- 비동기 액션 함수 내에서 비동기 작업을 수행하고, 필요에 따라 여러 액션을 디스패치할 수 있음
- 반환 형식:
(dispatch) => { /* 비동기 작업 수행 및 액션 디스패치 */ }
redux-thunk 설치와 코드 예제
설치
npm install redux-thunk
코드 예제
github: https://github.com/fromnowwon/redux-cafe-order-system
store.js
import { createStore, applyMiddleware } from "redux";
import rootReducer from "./rootReducer";
import logger from "redux-logger";
import { thunk } from "redux-thunk";
import { composeWithDevTools } from "redux-devtools-extension";
// 여러 middleware 배열로 관리
// thunk를 먼저 배치
const middleware = [thunk, logger];
// rootReducer를 사용하는 스토어 생성
const store = createStore(
rootReducer,
composeWithDevTools(applyMiddleware(...middleware))
);
export default store;
rootReducer.js
import { combineReducers } from "redux";
import orderReducer from "./order/reducer";
import customerReducer from "./customer/reducer";
// 모든 리듀서 통합
const rootReducer = combineReducers({
orders: orderReducer,
customers: customerReducer,
});
export default rootReducer;
reducer.js
import {
FETCH_CUSTOMER_REQUEST,
FETCH_CUSTOMER_SUCCESS,
FETCH_CUSTOMER_FAILURE,
} from "./types";
const initialState = {
items: [],
loading: false,
error: null,
};
const customerReducer = (state = initialState, action) => {
switch (action.type) {
case FETCH_CUSTOMER_REQUEST:
return {
...state,
loading: true,
};
case FETCH_CUSTOMER_SUCCESS:
return {
...state,
items: action.payload,
loading: false,
};
case FETCH_CUSTOMER_FAILURE:
return {
...state,
error: action.payload,
loading: false,
};
default:
return state;
}
};
export default customerReducer;
actions.js
import {
FETCH_CUSTOMER_REQUEST,
FETCH_CUSTOMER_SUCCESS,
FETCH_CUSTOMER_FAILURE,
} from "./types";
// 동기적인 액션 생성자: 데이터를 받아오는 요청이 시작됐음을 알리는 경우
export const fetchCustomerRequest = () => {
return {
type: FETCH_CUSTOMER_REQUEST,
};
};
// 동기적인 액션 생성자: 데이터를 성공적으로 받아온 경우
export const fetchCustomerSuccess = (customers) => {
return {
type: FETCH_CUSTOMER_SUCCESS,
payload: customers,
};
};
// 동기적인 액션 생성자: 데이터를 받아오는 과정에서 에러가 발생한 경우
export const fetchCustomerFailure = (err) => {
return {
type: FETCH_CUSTOMER_FAILURE,
payload: err,
};
};
// Thunk를 사용한 비동기 액션 생성자
export const fetchCustomer = () => {
// dispatch를 인자로 받는다
return async (dispatch) => {
try {
// 먼저 요청이 시작했음을 나타내는 액션 디스패치
dispatch(fetchCustomerRequest());
// 비동기 작업
const response = await fetch(
"<https://jsonplaceholder.typicode.com/users>"
);
const customers = await response.json();
// 비동기 작업 완료 후 성공 시 액션 디스패치
dispatch(fetchCustomerSuccess(customers));
} catch (error) {
// 비동기 작업 실패 시 액션 디스패치
dispatch(fetchCustomerFailure(error.message));
}
};
};
반응형