[React-Query] Dependant Query

스머리·2024년 3월 18일
0

React-Query

목록 보기
6/6

Dependant Query

두 쿼리가 의존관계에 있어 특정 순서대로 실행되어야 하는 경우에는 어떻게 해야 할까?
예를 들어, 첫 번째 쿼리는 유저의 정보를 받아 오고, 두번째 쿼리는 받아온 유저의 정보에서 아이디를 이용해 해당 유저의 프로젝트를 받아 온다.

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옵션은 쿼리의 순서를 정하기 위해 사용하기보다는 어떤 쿼리를 바로 실행하지 않고 특정한 값이 있거나 특정 상황이 되었을 때 실행하도록 하는 등 다양한 시나리오에서 활용할 수 있다.

useQuery()에서 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;

profile
꾸준히 나아가는 프론트엔드 개발자

0개의 댓글

관련 채용 정보