강의

멘토링

커뮤니티

Inflearn コミュニティ Q&A

dogmnil20074517 のプロフィール画像
dogmnil20074517

投稿した質問数

Next + React Query で SNS サービスを作成する

インフィニットスクロール

useInfiniteQuery promise와 react use 사용시 페이지 무한 로딩

作成

·

85

0

리액트 쿼리의 suspense 스트리밍 기능 구현 중 버그가 발생해 인사이트를 얻고자 질문드립니다.

상위 컴포넌트에서 useInfiniteQuery로 promise를 반환하고, 해당 promise를 자식 컴포넌트의 props로 넘긴 뒤 React의 use hook으로 감싸서 data를 반환하도록 구현했습니다. 그리고 promise를 throw하는 자식 컴포넌트를 Suspense로 감싸서 promise를 캐치하도록 했는데요.

페이지 렌더링 자체는 정상적으로 되는데, request가 완료되지 않는 문제가 있습니다. 크롬 개발자도구의 Network 탭에서 document를 확인하면 "Caution: request is not finished yet"이라는 경고가 표시됩니다.

TanStack Query 공식 문서에도 useInfiniteQuery의 promise 사용 시 "This can be used with React.use() to fetch data"라고 명시되어 있어 React use와 함께 사용하라고 안내하고 있는데, 혹시 이 문제의 원인을 알 수 있을까요?

참고로 prefetch는 안했습니다. 그리고 prefetch 안하는 방법으로 suspense 스트리밍을 구현하고 싶습니다.

 

코드는 아래와 같습니다. 감사합니다!

 

export default function DetailReviewWrapper({ pid, userId }: DetailReviewProps) {
  const { infoData, observerRef, isFetchingNextPage, refetch, promise } = useReviewListInfinity({
    userId,
    pid,
  })
  return (
    <Suspense fallback={<DetailReviewLoading />}>
      <DetailReview
        pid={pid}
        userId={userId}
        promise={promise}
        refetch={refetch}
        isFetchingNextPage={isFetchingNextPage}
        observerRef={observerRef}
      />
    </Suspense>
  )
}
export default function DetailReview({
  pid,
  userId,
  promise,
  refetch,
  isFetchingNextPage,
  observerRef,
}: DetailReviewProps) {

  const data = use(promise)

  return (
    <>
      <section>
 <ReviewListView
          userId={userId}
          pid={pid}
          data={data?.list || []}
          className={cn('review-list')}
          refetch={refetch}
          showPoint
        />
        {isFetchingNextPage && <Loading />}
        <div ref={observerRef} />   
   </section>
export function useReviewListInfinity(params: UseReviewListInfinityProps) {
  const section = useSearchParams().get('contentType') as SectionType
  const orderType = useRecoilValue(commentOrderState)
  const filterType = useRecoilValue(filterTypeState)

  const { fetchNextPage, hasNextPage, isFetchingNextPage, isLoading, refetch, promise } = useInfiniteQuery({
    queryKey: [REVIEW_LIST_KEY, params, orderType, filterType, section],
    queryFn: ({ pageParam = 1 }) =>
      getReviewApi({
        uid: params.userId,
        pid: params.pid,
        section,
        pageInfo: {
          curPage: pageParam,
          pageSize: 20,
        },
        orderType: orderType === 'RECOMMENDED' ? 'like' : 'date',
        filterType,
      }),
    select: (data) => {
      return {
        list: data.pages.flatMap((page) => page.data.list),
        info: data.pages[0].data.info,
      }
    },
    getNextPageParam: (lastPage) => {
      const nextPage = lastPage.data.pageInfo.curPage + 1
      return nextPage <= lastPage.data.pageInfo.pageCount ? nextPage : undefined
    },
    initialPageParam: 1,
  })

  const { observerRef } = useIntersectionObserver({
    onScroll: () => {
      if (hasNextPage && !isFetchingNextPage) {
        fetchNextPage()
      }
    },
  })

  return {
    isLoading,
    isFetchingNextPage,
    observerRef,
    refetch,
    promise,
  }
}
const getQueryClient = (): QueryClient =>
  new QueryClient({
    defaultOptions: {
      queries: {
        refetchOnWindowFocus: false,
        refetchInterval: false,
        refetchOnReconnect: true,
        refetchOnMount: true,
        staleTime: Infinity,
        gcTime: Infinity,
        retry: false,
        experimental_prefetchInRender: true,
      },
    },
  })

 

무한 로딩 시 개발자 도구 캡쳐이미지입니다.

 

스크린샷 2025-11-03 오후 5.42.48.png

 

reactnext.jsreact-querynext-authmsw

回答 1

0

zerocho님의 프로필 이미지
zerocho
インストラクター

useInfiniteQuery가 promise를 return하나요? 공식문서에서도 본 적이 없는 용법이라...

https://tanstack.com/query/latest/docs/framework/react/reference/useInfiniteQuery

요기 문서 보시면 promise를 return하는걸로 나와있긴 합니다. 근데 promise를 사용하는 레퍼런스가 많이 없긴 하더라구요...

 

const {
  fetchNextPage,
  fetchPreviousPage,
  hasNextPage,
  hasPreviousPage,
  isFetchingNextPage,
  isFetchingPreviousPage,
  promise,
  ...result
} = useInfiniteQuery({
  queryKey,
  queryFn: ({ pageParam }) => fetchPage(pageParam),
  initialPageParam: 1,
  ...options,
  getNextPageParam: (lastPage, allPages, lastPageParam, allPageParams) =>
    lastPage.nextCursor,
  getPreviousPageParam: (firstPage, allPages, firstPageParam, allPageParams) =>
    firstPage.prevCursor,
})

 

zerocho님의 프로필 이미지
zerocho
インストラクター

아, 깃헙 이슈에도 질문 올리셨군요. 실험적 기능이라 라이브러리 자체 버그 여부도 판단해봐야겠습니다.

앗 보셨군요ㅋㅋㅋㅋ

useInfiniteQuery promise 대신 useSuspenseInfiniteQuery 사용하니까 해결되긴 했습니다. 제로초님 답변처럼 실험적 기능에 의한 버그이지 않을까 싶네요

아무튼 빠른 답변 감사합니다!

dogmnil20074517 のプロフィール画像
dogmnil20074517

投稿した質問数

質問する