태그
목차

플레이스홀더 쿼리 데이터

생성일: 2024-03-23

수정일: 2024-03-23

플레이스홀더 데이터란?

플레이스홀더 데이터를 사용하면 initialData 옵션과 유사하게 마치 쿼리에 이미 데이터가 있는 것처럼 동작할 수 있지만, 데이터가 캐시에 영구 저장되지는 않는다. 이는 실제 데이터가 백그라운드에서 가져와지는 동안 쿼리를 성공적으로 렌더링하기에 충분한 부분적(또는 가짜) 데이터가 있는 상황에 유용하다.

예시: 개별 블로그 게시물 쿼리는 제목과 게시물 본문의 작은 일부분만 포함하는 블로그 게시물 목록의 부모에서 "미리보기" 데이터를 가져올 수 있다. 이 부분 데이터를 개별 쿼리의 쿼리 결과에 영구적으로 저장하고 싶지는 않겠지만, 실제 쿼리가 전체 객체를 가져오는 것을 완료하는 동안 가능한 한 빨리 콘텐츠 레이아웃을 보여주는 데 유용하다.

캐시에 쿼리에 필요한 플레이스홀더 데이터를 제공하는 몇 가지가 방법이 있다:

placeholderData 를 사용하면 쿼리는 pending 상태가 되지 않는다. 표시할 data 가 있기 때문에 쿼리는 success 상태로 시작되며, 이는 "실제" 데이터가 아닌 그저 "플레이스홀더" 데이터일 수도 있다. "실제" 데이터와 구분하기 위해 쿼리 결과에서 isPlaceholderData 플래그가 true 로 설정된다.

값으로서의 플레이스홀더 데이터

function Todos() {
  const result = useQuery({
    queryKey: ['todos'],
    queryFn: () => fetch('/todos'),
    placeholderData: placeholderTodos,
  });
}

플레이스홀더 데이터 메모이제이션

쿼리의 플레이스홀더 데이터에 액세스하는 과정이 부담스럽거나 모든 렌더링마다 수행하고 싶지 않은 경우, 값을 메모이제이션할 수 있다:

function Todos() {
  const placeholderData = useMemo(() => generateFakeTodos(), []);
  const result = useQuery({
    queryKey: ['todos'],
    queryFn: () => fetch('/todos'),
    placeholderData,
  });
}

함수로서의 플레이스홀더 데이터

placeholderData 에는 함수를 사용할 수도 있다. 이 함수에서는 "이전" 성공한 쿼리의 데이터와 쿼리 메타 정보에 접근할 수 있다. 이는 한 쿼리의 데이터를 다른 쿼리의 플레이스홀더 데이터로 사용하려는 상황에 유용하다. 예를 들어 QueryKey가 ['todos', 1] 에서 ['todos', 2] 로 변경될 때, 데이터가 한 쿼리에서 다음 쿼리로 전환 되는 동안 로딩 스피너를 표시하는 대신 "이전" 데이터를 계속 표시할 수 있다. 자세한 내용은 페이지네이션 쿼리를 참조한다.

const result = useQuery({
  queryKey: ['todos', id],
  queryFn: () => fetch(`/todos/${id}`),
  placeholderData: (previousData, previousQuery) => previousData,
});

캐시로부터의 플레이스홀더 데이터

어떤 경우에는 다른 쿼리의 캐시된 결과에서 쿼리에 대한 플레이스홀더 데이터를 제공할 수 있다. 이에 대한 좋은 예는 블로그 게시물 목록 쿼리의 캐시된 데이터에서 게시물의 미리보기 버전을 검색한 다음, 이를 개별 게시물 쿼리의 플레이스홀더 데이터로 사용하는 것이다:

function Todo({ blogPostId }) {
  const queryClient = useQueryClient();
  const result = useQuery({
    queryKey: ['blogPost', blogPostId],
    queryFn: () => fetch(`/blogPosts/${blogPostId}`),
    placeholderData: () => {
      // '블로그 게시물' 쿼리에서 블로그 게시물의 작은/미리보기 버전을 이 블로그 게시물 쿼리의 플레이스홀더 데이터로 사용한다.
      return queryClient
        .getQueryData(['blogPosts'])
        ?.find((d) => d.id === blogPostId);
    },
  });
}