사이드 프로젝트를 진행하던 중에 버튼을 클릭했을 때, 혹은 form을 submit 했을 때 API data fetch을 하도록 구현해야 하는 부분이 있었다.
지금까지의 data fetch를 할 때, 렌더링하기 위한 데이터 전체를 fetch하는 경우가 대부분이었다.
예를 들어 Netflix 클론 코딩의 경우, main 홈페이지에서는 자동으로 영화 정보 data를 fetch하여 렌더링하고, 주문 내역 관리 홈페이지 같은 경우도 동일하게 main 페이지로 들어가면 렌더링해주는 정보가 결국 해당 페이지에서 fetch한 주문 내역 data이다.
하지만 이 프로젝트의 경우, 사용자가 입력한 질문을 OpenAI 를 활용한 api에 input으로 request(post)를 보내고, api의 response를 렌더링해주는 로직이 필요했다.
구글링 해본 결과, useMutation
을 사용하라는 답변도 있었는데 적절한 사용은 아니다. useMutation
는 CRUD 처럼 함수 이름 그대로 Data의 mutate가 일어나는 request일 경우 사용하는 함수이다.
Unlike queries, mutations are typically used to create/update/delete data or perform server side-effects. For this purpose, TanStack Query exports a useMutation hook. 공식문서
이 프로젝트에서는 request body로 사용자의 입력인 질문을 넣어 api 요청을 하면, api는 해당 input에 대한 response를 보내준다.
따라서 useMutation
이 아닌 enabled:false
옵션 처리와 refetch
함수를 사용하여 구현하였다.
enabled=false
쿼리가 자동으로 동작하는 것을 막고 싶다면, enabled=false
option을 사용하면 된다.
enabled=false
일 때,캐시된 데이터가 있다면, 해당 쿼리의 status
는 success
또는 isSuccess
상태로 initialize 된다
캐시된 데이터가 없다면, 해당 쿼리의 status
는 loading
또는 fetchStatus === 'idle'
로 initialize 된다.
마운트 시 쿼리는 자동으로 fetch를 수행하지 않는다.
백그라운드에서 refetch을 자동으로 수행하지 않는다.
쿼리는 query client invalidateQueries
와 refetchQueries
호출을 무시한다. (보통, 호출 결과 query refetch가 수행됨)
useQuery
로부터 return되는 refetch
함수를 사용하여 수동으로 refetch를 수행하도록 할 수 있다.
아래는 구현한 data fetch를 위한 custom hook 함수이다.
export default function useAnswer({ guess_word, question }: IReqBody) {
return useQuery({
queryKey: ['gptAnswer'],
queryFn: () => getOpenAIResponse({ guess_word: guess_word, question: question }),
refetchOnWindowFocus: false,
enabled: false,
});
}
onSubmit
함수에서 useQuery
의 return 값인 refetch
함수를 사용하면, form 이 submit 되었을 때 refetch가 수행된다.
실제 사용은 아래처럼 하였다.
const { isFetching, data, refetch } = useAnswer({ guess_word, question });
const onSubmitQuestion = (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();
refetch(); // 여기!
};
컴포넌트 렌더링 부분은 아래와 같다.
{data ? (
isFetching ? (
<Spinner />
) : (
<Container bg="gray.100" padding="30px" borderRadius="10px">
<Text>{data?.gpt_response}</Text>
</Container>
)
) : null}
ReactQueryDevtools
로 확인하면 submit 되었을 때만 fetching을 수행하는 걸 확인할 수 있다.
참고