두 쿼리가 의존관계에 있어 특정 순서대로 실행되어야 하는 경우에는 어떻게 해야 할까?
예를 들어, 첫 번째 쿼리는 유저의 정보를 받아 오고, 두번째 쿼리는 받아온 유저의 정보에서 아이디를 이용해 해당 유저의 프로젝트를 받아 온다.
const { data: user } = useQuery({
queryKey: ['user', email],
queryFn: getUserByEmail,
});
const userId = user?.id
const {
data: projects,
} = useQuery({
queryKey: ['projects', userId],
queryFn: getProjectsByUser,
});
이런 상황에서는 useQuery()
의 enabled
옵션을 사용한다. enabled
값이 true
가 되어야만 해당 쿼리가 실행된다. 이렇게 어떤 특정한 값이나 조건이 충족된 이후에 실행되는 쿼리를 Dependant Query라고 한다.
만약 어떤 쿼리가 userId
값이 있을 때만 실행하도록 하고 싶으면 다음과 같이 설정한다.
const { data: user } = useQuery({
queryKey: ['user', email],
queryFn: getUserByEmail,
});
const userId = user?.id
const {
data: projects,
} = useQuery({
queryKey: ['projects', userId],
queryFn: getProjectsByUser,
enabled: !!userId,
});
userId
가 있는 경우 true
, false
로 옵션값이 설정됨위 상황에서는 두 개의 쿼리를 순서대로 실행하려고 enabled
옵션을 사용했지만, enabled
옵션값으로 꼭 이전 쿼리에서 가져온 데이터가 들어가야만 하는 것은 아니다. 위의 경우도 백엔드 API 설계에 따라서 두번의 쿼리가 아니라 한 번의 쿼리로 끝낼 수 있음!
예를 들어 getProjectByUserEmail()
이라는 함수를 통해 유저의 이메일 주소를 백엔드로 전달하고, 그에 맞는 유저의 프로젝트를 받을 수 있는 API가 있다면 한 번의 쿼리로 끝낼 수 있다.
실제로 enabled
옵션은 쿼리의 순서를 정하기 위해 사용하기보다는 어떤 쿼리를 바로 실행하지 않고 특정한 값이 있거나 특정 상황이 되었을 때 실행하도록 하는 등 다양한 시나리오에서 활용할 수 있다.
enabled
값을 활용하여 로그인 기능 만들기.
currentUsername
이라는 스테이트 값을 만들어 사용.currentUsername
을 'sumuri'
라는 값으로 설정하고, 이 값이 있을 때 userInfo
쿼리를 실행// src/api.js
const BASE_URL = 'https://learn.codeit.kr/api/codestudit';
// ...
export async function getUserInfo(username) {
const response = await fetch(`${BASE_URL}/users/${username}`);
return await response.json();
}
// HomePage.js
import { useState } from 'react';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { getPosts, uploadPost, getUserInfo } from './api';
function HomePage() {
const [currentUsername, setCurrentUsername] = useState('');
// ...
const { data: userInfoData, isPending: isUserInfoPending } = useQuery({
queryKey: ['userInfo'],
queryFn: () => getUserInfo(currentUsername),
enabled: !!currentUsername,
});
// ...
const handleLoginButtonClick = () => {
setCurrentUsername('sumuri');
};
const loginMessage = isUserInfoPending
? '로그인 중입니다...'
: `${userInfoData?.name}님 환영합니다!`;
if (isPending) return '로딩 중입니다...';
if (isError) return '에러가 발생했습니다.';
const posts = postsData?.results ?? [];
return (
<>
<div>
{currentUsername ? (
loginMessage
) : (
<button onClick={handleLoginButtonClick}>codeit으로 로그인</button>
)}
<form onSubmit={handleSubmit}>
<textarea
name="content"
value={content}
onChange={handleInputChange}
/>
<button disabled={!content} type="submit">
업로드
</button>
</form>
</div>
<div>
<ul>
{posts.map((post) => (
<li key={post.id}>
{post.user.name}: {post.content}
</li>
))}
</ul>
</div>
</>
);
}
export default HomePage;