queryKey와 enabled를 사용해 어떤 데이터가 다른 데이터에 의존할 때, 올바른 순서로 요청하고 관리할 수 있다.
const { data: user } = useQuery({
queryKey: ['user', userId],
queryFn: () => fetchUser(userId),
enabled: Boolean(userId), // userId가 있어야 실행
});
const { data: posts } = useQuery({
queryKey: ['posts', user?.id],
queryFn: () => fetchPosts(user?.id), // user가 있어야 실행
enabled: Boolean(user), // user 데이터가 존재할 때만 실행
});
여러개의 useQuery를 한번에 실행시켜주는 훅이다. 각 요청을 병렬로 실행해서 성능 최적화가 가능하다.
기본 사용법
useQueries는 배열로 쿼리들을 받고 배열로 결과를 반환한다.
results는 각 useQuery의 반환값을 포함한 배열이라서 아래처럼 접근할 수 있다.
results[0].data → user 데이터
results[1].data → posts 데이터
const results = useQueries({
queries: [
{
queryKey: ['user', userId],
queryFn: () => fetchUser(userId)
},
{
queryKey: ['posts', userId],
queryFn: () => fetchPosts(userId)
},
],
});
useQueries는 배열을 받기 때문에, 동적인 개수의 쿼리도 실행할 수 있다.
const userIds = [1, 2, 3]; // 여러 개의 userId
const userQueries = useQueries({
queries: userIds.map((id) => ({
queryKey: ['user', id],
queryFn: () => fetchUser(id),
enabled: !!id,
})),
});
응답 상태 다루기
some 메서드로 하나라도 로딩중/에러 라면 isLoading/isError를 true로 설정한다.
const isLoading = userQueries.some(query => query.isLoading);
const isError = userQueries.some(query => query.isError);
const users = userQueries.map(query => query.data).filter(Boolean);
useQueries의 combine 옵션으로 여러개의 쿼리 결과를 하나의 객체로 합칠 수 있다.
여러개의 쿼리 데이터를 원하는 형식으로 변환하고, isPending, isError 등의 상태도 원하는 대로 계산할 수 있다.
const ids = [1, 2, 3];
const combinedQueries = useQueries({
queries: ids.map(id => ({
queryKey: ['post', id],
queryFn: () => fetchPost(id),
})),
combine: (results) => {
return {
data: results.map(result => result.data), // 각 쿼리의 데이터를 배열로 정리
pending: results.some(result => result.isPending), // 하나라도 로딩 중이면 true
// 모든 데이터를 성공적으로 받아오면 true
allSuccess: results.every(result => result.status === 'success')
};
},
});