반복된 코드
export async function getUsers(dispatch) {
dispatch({ type: 'GET_USERS' });
try {
const response = await axios.get(
'https://jsonplaceholder.typicode.com/users'
);
dispatch({ type: 'GET_USERS_SUCCESS', data: response.data });
} catch (e) {
dispatch({ type: 'GET_USERS_ERROR', error: e });
}
}
export async function getUser(dispatch, id) {
dispatch({ type: 'GET_USER' });
try {
const response = await axios.get(
`https://jsonplaceholder.typicode.com/users/${id}`
);
dispatch({ type: 'GET_USER_SUCCESS', data: response.data });
} catch (e) {
dispatch({ type: 'GET_USER_ERROR', error: e });
}
}
이 부분을 깔끔하게 리팩토링 해보자. src 디렉토리 하위에 api.js 파일을 만들고 다음과 같이 작성한다.
api.js
import axios from 'axios';
export async function getUsers() {
const response = await axios.get(
'https://jsonplaceholder.typicode.com/users'
);
return response.data;
}
export async function getUser(id) {
const response = await axios.get(
`https://jsonplaceholder.typicode.com/users/${id}`
);
return response.data;
}
그 다음에 src 디렉터리에 asyncActionUtils.js라는 파일을 만들고 코드를 작성한다.
asyncActionUtils.js
// 이 함수는 파라미터로 액션의 타입 (예: GET_USER) 과 Promise 를 만들어주는 함수를 받아옵니다.
export default function createAsyncDispatcher(type, promiseFn) {
// 성공, 실패에 대한 액션 타입 문자열을 준비합니다.
const SUCCESS = `${type}_SUCCESS`;
const ERROR = `${type}_ERROR`;
// 새로운 함수를 만듭니다.
// ...rest 를 사용하여 나머지 파라미터를 rest 배열에 담습니다.
async function actionHandler(dispatch, ...rest) {
dispatch({ type }); // 요청 시작됨
try {
const data = await promiseFn(...rest); // rest 배열을 spread 로 넣어줍니다.
dispatch({
type: SUCCESS,
data
}); // 성공함
} catch (e) {
dispatch({
type: ERROR,
error: e
}); // 실패함
}
}
return actionHandler; // 만든 함수를 반환합니다.
}
이렇게 만들어주면 Context 파일이 깔끔해진다.
UserContext.js
import React, { createContext, useReducer, useContext } from 'react';
import createAsyncDispatcher from './createAsyncDispatcher';
import * as api from './api'; // api 파일에서 내보낸 모든 함수들을 불러옴
(...)
export const getUsers = createAsyncDispatcher('GET_USERS', api.getUsers);
export const getUser = createAsyncDispatcher('GET_USER', api.getUser);
그다음 리듀서쪽 코드도 리팩토링해보자. UsersContext의 lodingState, success, error를 잘라내서 asyncActionUtils.js 안에 붙여넣고 initialAsyncState 객체와 createAsyncHandler 함수를 만들어서 내보낸다.
이제 방금만든 initialAsyncState와 createAsyncHandler를 사용해서 코드를 고쳐보자.
UsersContext.js
import React, { createContext, useReducer, useContext } from 'react';
import {
createAsyncDispatcher,
createAsyncHandler,
initialAsyncState
} from './asyncActionUtils';
import * as api from './api'; // api 파일에서 내보낸 모든 함수들을 불러옴
// UsersContext 에서 사용 할 기본 상태
const initialState = {
users: initialAsyncState,
user: initialAsyncState
};
const usersHandler = createAsyncHandler('GET_USERS', 'users');
const userHandler = createAsyncHandler('GET_USER', 'user');
// 위에서 만든 객체 / 유틸 함수들을 사용하여 리듀서 작성
function usersReducer(state, action) {
switch (action.type) {
case 'GET_USERS':
case 'GET_USERS_SUCCESS':
case 'GET_USERS_ERROR':
return usersHandler(state, action);
case 'GET_USER':
case 'GET_USER_SUCCESS':
case 'GET_USER_ERROR':
return userHandler(state, action);
default:
throw new Error(`Unhanded action type: ${action.type}`);
}
}
(...)
이렇게 리팩토링을 하면 반복되는 코드를 함수화해서 재사용 할 수 있다.
'Front-End > React.js' 카테고리의 다른 글
React.js | Intersection Observer(무한 스크롤) (4) | 2021.11.14 |
---|---|
React.js | CSS, SASS, SCSS (0) | 2021.11.02 |
React.js | API 연동 | Context 와 함께 사용하기 (0) | 2021.10.07 |
React.js | API 연동 | react-async로 요청 상태 관리하기 (0) | 2021.10.07 |
React.js | API 연동 | useAsync 커스텀 Hook (0) | 2021.10.07 |