Skip to Content
๐Ÿ‘€ Suspensive v3์—์„œ์˜ ๋ณ€๊ฒฝ์„ ํ™•์ธํ•˜์„ธ์š”. ๋”๋ณด๊ธฐ

useSuspenseInfiniteQuery

์ด hook์˜ return ํƒ€์ž…์—๋Š” isLoading, isError์ด ์—†์Šต๋‹ˆ๋‹ค. <Suspense/> and <ErrorBoundary/>๊ฐ€ ์ด hook์˜ data๋ฅผ ๋ณด์žฅํ•ด์ฃผ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋˜ํ•œ, ์ด hook์˜ options์—๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ suspense๊ฐ€ true์ž…๋‹ˆ๋‹ค. ํ•„์š”ํ•œ ์ƒˆ options๋Š” @tanstack/react-query์˜ useInfiniteQueryโ€‰์ฒ˜๋Ÿผ ์‚ฌ์šฉํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

import { useSuspenseInfiniteQuery } from '@suspensive/react-query' const Example = () => { const query = useSuspenseInfiniteQuery({ queryKey, queryFn, }) // suspense ์˜ต์…˜์€ true๊ฐ€ ๊ธฐ๋ณธ์ž…๋‹ˆ๋‹ค. // isSuccess์œผ๋กœ type narrowing์ด ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. query.data // InfiniteData<TData> }
import { useSuspenseInfiniteQuery } from '@suspensive/react-query'
import { useEffect, Fragment } from 'react'
import { getPosts } from './api'

export const Posts = () => {
  const { data, isFetchingNextPage, isFetched, hasNextPage, fetchNextPage } =
    useSuspenseInfiniteQuery({
      queryKey: ['posts'],
      queryFn: ({ pageParam = 1 }) => getPosts(pageParam),
      getNextPageParam: (lastPage, allPages) =>
        lastPage.skip + lastPage.limit < lastPage.total
          ? allPages.length + 1
          : undefined,
    })

  useEffect(() => {
    if (!isFetchingNextPage && isFetched) {
      window.scrollTo({
        top: document.body.scrollHeight,
        behavior: 'smooth',
      })
    }
  }, [isFetchingNextPage, isFetched])

  return (
    <div
      style={{
        display: 'flex',
        flexDirection: 'column',
        marginBottom: '100px',
      }}
    >
      <ol>
        {data.pages.map((page, i) => (
          <Fragment key={i}>
            {page.data.map((post) => (
              <li key={post.id} style={{ marginBottom: '10px' }}>
                {post.title}
              </li>
            ))}
          </Fragment>
        ))}
      </ol>
      <button
        onClick={() => fetchNextPage()}
        disabled={!hasNextPage || isFetchingNextPage}
      >
        {isFetchingNextPage
          ? 'Loading more...'
          : hasNextPage
            ? 'Load More'
            : 'Nothing more to load'}
      </button>
    </div>
  )
}

๋™๊ธฐ

@tanstack/react-query์—์„œ suspense ์˜ต์…˜์„ ์‚ฌ์šฉํ•˜๋ฉด, useInfiniteQueryโ€‰๋ฅผ <Suspense/>, <ErrorBoundary/>์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

import { useInfiniteQuery } from '@tanstack/react-query' const Example = () => { const query = useInfiniteQuery({ queryKey, queryFn, suspense: true, }) query.data // InfiniteData<TData> | undefined if (query.isSuccess) { query.data // InfiniteData<TData> } }

ํ•˜์ง€๋งŒ useInfiniteQuery์˜ return ํƒ€์ž…(query.data)์€ ์ด ์ปดํฌ๋„ŒํŠธ์˜ ๋ถ€๋ชจ์ธ <Suspense/> ๋•๋ถ„์— ํ•ญ์ƒ ์„ฑ๊ณตํ•œ ๊ฒฝ์šฐ์ผ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ด๊ฒƒ์ด @suspensive/react-query๊ฐ€ useSuspenseInfiniteQuery๋ฅผ ์ œ๊ณตํ•˜๋Š” ์ด์œ ์ž…๋‹ˆ๋‹ค.

๐Ÿ’ก

์„ฑ๊ณตํ•œ ์ผ€์ด์Šค์— ์ง‘์ค‘ํ•˜์„ธ์š”.

์ด์ œ ์šฐ๋ฆฌ๋Š” ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์—์„œ fetching์ด ํ•ญ์ƒ ์„ฑ๊ณตํ•˜๋ฏ€๋กœ ์„ฑ๊ณตํ•œ ๊ฒฝ์šฐ์—๋งŒ ์ง‘์ค‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฒ„์ „ ๊ธฐ๋ก

VersionChanges
v3.0.0networkMode๋Š” 'always'๋กœ ๊ณ ์ •๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ v3๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ํ•˜๊ธฐ ๋ฌธ์„œ๋ฅผ ์ฐธ๊ณ ํ•˜์„ธ์š”.
์ˆ˜์ •๋œ ๋‚ ์งœ: