최근 사이드 프로젝트를 하며 react-query
를 공부하는 중입니다.👩💻
호출과 동시에 get 요청을 하거나 useMutation
을 사용하여 데이터를 수정하는 예시들은 많은데,
의외로 버튼을 눌렀을 때 get 요청을 보낸다!
의 예시가 잘 보이지 않아 쌩뉴비 입장에서 쪼금.. 난감했습니다 😵
조건이 true
일 때 쿼리를 실행하는 옵션이 있다는 것은 알고 있었습니다만
서버에서 받아온 데이터를 useState
로 관리하기 싫어서 라이브러리를 쓰는 건데,
쿼리를 불러올 조건을 관리하기 위한 state를 또 만드는 게 맞나? 싶은 생각이 들어서 찾아봤더니 민망할 정도로 간단한 방법이 있었습니다💀 복습하는 겸 블로그에 기록해보았습니다.
react-query
는 웹 애플리케이션을 위한 라이브러리로, 서버에서 데이터 가져오기, 캐싱, 데이터 동기화 및 업데이트를 쉽게 만들어줍니다.
react-query
를 사용하지 않고 일반적으로 클라이언트에서 데이터를 fetch하는 방법은 다음과 같습니다.
type Post = {
date: string;
headline: string;
href: string;
context?: string;
tags?: string;
};
const [data, setData] = useState<Post[] | null>(null);
const [isLoading, setIsLoading] = useState(true);
const [isError, setIsError] = useState(false);
useEffect(() => {
(async () => {
const res = axios.get(YOUR_API_HERE);
try {
const resData = await res;
setData(resData.data);
} catch (e) {
console.log(e);
setIsError(true);
} finally {
setIsLoading(false);
}
})();
}, []);
useEffect(() => {
console.log(isLoading, data, isError);
}, [isLoading, data, isError]);
api 하나 호출하는 것 뿐인데 코드 양이 쓸데없이 장황합니다.😵
같은 내용을 react-query
로 바꾸어 fetch해 보겠습니다.
const { isLoading, data, error } = useQuery('postList', async () => {
const res = await axios.get(YOUR_API_HERE);
return res.data;
});
useEffect(() => {
console.log(isLoading, data, error);
}, [isLoading, data, error]);
isLoading
등의 status를 기본적으로 제공해 주기 때문에,
api 호출 시 loading 상태와 error상태를 따로 바꿔줄 필요가 없어 매우 간결해졌습니다.
이 외에도 다른 창을 포커스했다가 윈도우가 다시 포커스되었을 때, 일정 시간마다 데이터 다시 fetch하기, 동일한 데이터에 대한 여러 요청을 단일 요청으로 중복 제거하기 등등 여러가지 편리한 기능들을 제공해 줍니다.
react-query
는 호출과 동시에 데이터를 fetch해 옵니다.
그런데 개발하다 보면 마운트됐을 때 뿐만이 아닌, 버튼을 클릭했을 때 데이터를 받아와야 한다던가, 특정 조건이 발동되었을 때 데이터를 받아온다던가...🤤 하는 일이 있습니다.
react-query
에서 get
요청을 수행하는 역할을 하는 useQuery
는 첫번째 파라미터로 쿼리 키 값이, 두번째 파라미터로는 api를 요청하는 함수가, 세번째 파라미터로는 옵션 값이 들어갑니다.
그 중 enabled
라는 옵션이 있는데, 키의 값으로 주어지는 조건이 true
일때만 쿼리를 실행하는 옵션입니다.
const {
status,
fetchStatus,
data: projects,
} = useQuery({
queryKey: ['projects', userId],
queryFn: getProjectsByUser,
enabled: !!userId, // userId가 true 일때만 쿼리 실행
})
값이 false
일 때는 쿼리가 자동으로 실행되지 않으며, 이를 이용해 초기에 자동으로 쿼리가 실행되는 것을 방지할 수 있습니다.
useQuery
hook에는 isLoading
, isStale
, failureCount
같은 다양한 속성이 있습니다. 그 중에 refetch
라는 속성도 있습니다.
refetch: (options: { throwOnError: boolean, cancelRefetch: boolean }) => Promise<UseQueryResult>
refetch 속성은 쿼리를 수동으로 실행하는 함수입니다.
앞의 enabled
옵션과 같이 사용하면 처음에 선언되었을 때는 데이터 fetch를 하지 않다, 클릭 이벤트가 발생했을 때나 특정 조건에서(state를 따로 또 만들어 주지 않고!) 데이터를 fetch 해올 수 있습니다. 😀
const { isLoading, data, error, refetch } = useQuery(
'postList',
async () => {
const res = await axios.get(YOUR_API_ADDRESS);
return res.data;
},
{
enabled: false,
}
);
const onClickButton = () => {
console.log('데이터를 다시 가져왔어요');
refetch();
};
useEffect(() => {
console.log(isLoading, data, error);
}, [isLoading, data, error]);