Skip to Content
API 레퍼런스HooksuseNexusInfiniteQuery

useNexusInfiniteQuery

useNexusInfiniteQuery는 ‘무한 스크롤’ 또는 ‘더 보기’ UI를 구축하기 위한 클라이언트 사이드 훅입니다. 페이지 파라미터, 데이터 페칭, 상태 집계를 관리합니다.

Import

import { useNexusInfiniteQuery } from 'next-nexus/client';

핵심 개념 (Core Concepts)

동작 방식

이 훅은 페이지 파라미터(예: 커서 또는 페이지 번호)를 인자로 받는 definition 팩토리 함수를 사용합니다. 이 함수를 순차적으로 호출하여 각 페이지를 가져옵니다. 사용자는 마지막으로 성공한 페이지의 데이터로부터 다음 페이지의 파라미터를 가져오는 방법을 알려주는 getNextPageParam 함수를 반드시 제공해야 합니다.

Foreground/Background 재검증

각 페이지의 재검증 로직은 useNexusQuery와 동일합니다. 새 페이지를 가져오거나(revalidateNext) 기존 페이지를 다시 가져올 때(revalidatePage):

  • Foreground: 페이지에 대한 캐시된 데이터가 없거나, keepStaleDatafalse이고 데이터가 만료(stale)된 경우. 이 때 isPending 상태가 됩니다.
  • Background: 만료된 데이터가 있고 keepStaleDatatrue인 경우. 이 때 isPendingBackground 상태가 됩니다.

상태 플래그와 UX

  • isPending: Foreground 페칭 중에 true가 됩니다. 초기 로딩 시 스켈레톤 UI나 ‘더 보기’ 버튼의 스피너와 같은 주요 로딩 상태를 표시하는 데 사용하세요.
  • isPendingBackground: Background 페칭 중에 true가 됩니다.
  • hasNextPage: 마지막 페이지에 대해 getNextPageParam 함수가 null 또는 undefined가 아닌 값을 반환했을 때 true가 됩니다.

시그니처 (Signature)

파라미터 (Parameters)

  • getDefinition: (param) => NexusDefinition<TPage> — 현재 페이지 파라미터를 받아 GET definition을 반환하는 팩토리 함수.
  • options: 훅의 동작을 설정하는 객체. 아래 Options를 참고하세요.

반환 값 (Return Value)

다음을 포함하는 객체:

  • data: { pages: TPage[], pageParams: unknown[] } | undefined
  • headers: Headers | undefined (가장 최근 요청의 헤더)
  • error: Error | null
  • isPending, isPendingBackground, isSuccess, isError: boolean
  • hasNextPage: boolean
  • revalidateNext: () => Promise<void> (다음 페이지를 가져옴)
  • prefetchRef?: React.Ref<HTMLDivElement> (선패치를 활성화하기 위한 sentinel 엘리먼트의 ref)

Options

  • initialPageParam: 가장 첫 페이지의 파라미터 (예: 페이지 번호는 0, 커서 기반은 null).
  • getNextPageParam: (lastPage: TPage, allPages: TPage[]) => param | null | undefined — 다음 페이지의 파라미터를 반환하는 함수. null 또는 undefined를 반환하면 마지막 페이지임을 나타냅니다.
  • keepPages?: number - 설정된 경우, 메모리 사용량을 제한하기 위해 가장 최근 N개의 페이지만 메모리에 유지합니다.
  • revalidateOnMount?: boolean (기본값: true)
  • revalidateOnWindowFocus?: boolean (기본값: false)
  • keepStaleData?: boolean (기본값: true)
  • prefetchNextOnNearViewport?: { rootMargin?: string, threshold?: number } - sentinel 엘리먼트가 뷰포트 근처에 있을 때 다음 페이지를 선패치(prefetch)합니다.

예제 (Example)

1. Definition 팩토리

먼저, 커서와 같은 페이지 파라미터를 받는 definition을 만듭니다.

// src/api/productDefinition.ts (일부) export interface InfiniteProduct { products: { id: string; name: string }[]; nextCursor?: string | null; } export const productDefinition = { infiniteList: (cursor: string | null) => createApiDefinition<InfiniteProduct>({ method: "GET", endpoint: cursor ? `/products?cursor=${cursor}` : "/products", client: { tags: ["products", `cursor:${cursor ?? "first"}`], revalidate: 300, }, }), };

2. 컴포넌트 사용법

그 다음, 컴포넌트에서 훅을 사용합니다.

"use client"; import { useNexusInfiniteQuery } from "next-nexus/client"; import { productDefinition } from "@/api/productDefinition"; export default function InfiniteProductList() { const { data, hasNextPage, revalidateNext, prefetchRef, isPending } = useNexusInfiniteQuery(productDefinition.infiniteList, { initialPageParam: null, getNextPageParam: (lastPage) => lastPage?.nextCursor ?? null, prefetchNextOnNearViewport: { rootMargin: "200px" }, }); const allProducts = data?.pages.flatMap((page) => page.products) ?? []; return ( <div> <ul> {allProducts.map((p) => ( <li key={p.id}>{p.name}</li> ))} </ul> <button onClick={() => revalidateNext()} disabled={!hasNextPage || isPending} > {isPending ? "로딩 중…" : "더 보기"} </button> {/* 옵션: 선패치를 위한 sentinel 엘리먼트 */} <div ref={prefetchRef} style={{ height: 1 }} /> </div> ); }

함께 보기

Last updated on