
이전 프로젝트 때, 커스텀 훅을 본인이 담당해서 만든 적이 있었다. 하지만, 그 당시에 만들었던 커스텀 훅은 굉장히 부실해 보였고, 이를 보완하기 위해서 다시 만들었다. 테스트는 해봤고, 아주 잘된다. 그래서 문제 없이 사용 가능하다.
import { useState } from "react";
interface APIState<T> {
data: T | null;
error: Error | null;
loading: boolean;
}
export function useAPI<T = any>(
method: string,
url: string,
): [APIState<T>, (body: any, headers?: any) => Promise<void>] {
const [response, setResponse] = useState<APIState<T>>({
data: null,
error: null,
loading: false,
});
const fetchData = async (body: any = null, headers: any = {}) => {
setResponse((state) => ({ ...state, loading: true }));
try {
const result = await fetch(url, {
method,
headers: { "Content-Type": "application/json", ...headers },
body: JSON.stringify(body),
}).then((response) => response.json() as T);
setResponse({ data: result, error: null, loading: false });
} catch (error:any) {
setResponse({ data: null, error, loading: false });
}
};
return [response, fetchData];
}
이 코드는 커스텀 훅인 useAPI를 정의하고 있습니다. 커스텀 훅은 특정 로직을 재사용 가능하도록 만드는 것이 목적입니다. 이 useAPI 훅은 주어진 method와 url을 사용하여 네트워크 요청을 수행하고, 그에 대한 응답을 관리합니다.
코드를 좀 더 자세히 보면:
useState를 사용하여 response라는 state를 선언하고, 이 state는 API 응답을 관리합니다. 이 state는 data, error, loading 세 가지 필드를 갖는 객체입니다. data는 API 응답 데이터를, error는 발생한 오류를, loading은 로딩 상태를 나타냅니다.
fetchData 함수를 선언하였습니다. 이 함수는 주어진 body와 headers를 사용하여 API 요청을 보내고, 그 결과를 response state에 저장합니다. 이 함수는 비동기 함수로 선언되어 있어서, fetch가 반환하는 Promise를 사용하여 네트워크 요청을 비동기적으로 처리합니다.
fetchData 함수 내부에서는 먼저 로딩 상태를 true로 설정한 뒤, fetch를 사용하여 네트워크 요청을 보냅니다. fetch가 성공적으로 완료되면 그 결과를 response의 data 필드에 저장하고, 오류가 발생하면 error 필드에 저장합니다. 이 모든 작업이 완료되면 로딩 상태를 false로 설정합니다.
이 훅은 response와 fetchData를 반환합니다. 이들을 사용하여 컴포넌트에서 API 요청의 상태를 관리하고, 요청을 보낼 수 있습니다.
이 useAPI 훅은 API 요청과 그에 대한 응답을 편리하게 관리하고, 여러 컴포넌트에서 재사용할 수 있도록 해줍니다. 이 훅을 사용하면 컴포넌트 내에서 직접 fetch를 사용하고 그 결과를 관리하는 복잡한 로직을 피할 수 있습니다.
정리가 잘 된 글이네요. 도움이 됐습니다.