useReducer 를 사용하여 요청 상태관리
reducer
// LOADING, SUCCESS, ERROR
export function asyncReducer(state, action) {
switch (action.type) {
case "LOADING":
return {
loading: true,
data: null,
error: null,
};
case "SUCCES":
return {
loading: false,
data: action.data,
error: null,
};
case "ERROR":
return {
loading: false,
data: null,
error: action.error,
};
default:
throw new Error(`Unhandled action type: ${action.type}`);
}
}
api
const fetchUsers = async () => {
dispatch({ type: "LOADING" });
try {
const response = await axios.get(
"https://jsonplaceholder.typicode.com/users"
);
dispatch({ type: "SUCCES", data: response.data });
} catch (e) {
dispatch({ type: "ERROR", error: e });
}
};
reduer 를 사용하여 요청상태를 관리가능
사용
const [state, dispatch] = (reducer, initialstate)
import { useReducer, useEffect, useCallback } from "react";
// LOADING, SUCCESS, ERROR 요청 상태를 반홚하는 리듀서
export function asyncReducer(state, action) {
switch (action.type) {
case "LOADING":
return {
loading: true,
data: null,
error: null,
};
case "SUCCES":
return {
loading: false,
data: action.data,
error: null,
};
case "ERROR":
return {
loading: false,
data: null,
error: action.error,
};
default:
throw new Error(`Unhandled action type: ${action.type}`);
}
}
function useAsync(cb, deps = [], skip = false) {
const [state, dispatch] = useReducer(asyncReducer, {
loading: false,
data: null,
error: null,
});
// 콜백함수를 받아서 결과값을 리듀서로 전달
const fetchData = useCallback(async () => {
dispatch({ type: "LOADING" });
try {
const data = await cb();
dispatch({ type: "SUCCES", data });
} catch (error) {
dispatch({ type: "ERROR", error });
}
}, [cb]);
useEffect(() => {
if (!skip) {
return;
}
fetchData();
// eslint-disable-next-line
}, deps);
return [state, fetchData];
}
export default useAsync;
요청하는 API 함수
async function getUsers() {
try {
const result = await axios.get(
"https://jsonplaceholder.typicode.com/users"
);
return result.data;
} catch (e) {
return e;
}
}
커스텀훅을 사용하여 통신을 관리하면 여러곳에서 사용가능
한번 구성이 어렵더라도 여러곳에서 사용이 가능하기에 재사용성이 좋다.