inflearn logo
강의

講義

知識共有

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

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

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

98

dogmnil20074517

投稿した質問数 15

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

 

react next.js react-query next-auth msw

回答 1

0

zerocho

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

0

dogmnil20074517

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,
})

 

0

zerocho

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

0

dogmnil20074517

앗 보셨군요ㅋㅋㅋㅋ

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

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

캡처링부분 질문있습니다.

0

74

2

깃에 소스코드를 찾을 수 없습니다.

0

113

2

import 파일 경로를 찾지 못 해서 에러가 발생합니다.

0

109

2

css 라이브러리 추천 부탁드립니다

0

140

2

팔로우 추천 목록이 빈 배열로 들어옵니다.

0

130

1

게시물 업로드 시 userId가 undefined로 들어가는 오류

0

119

1

useSuspenseQuery 사용 시 SSR 401 이슈 관련

0

171

1

리액트 쿼리 useinfinitequery 무한스크롤 구현 시 페이지가 이동할 경우 데이터가 보존되게 할 수 있나요??

0

184

3

폴링이 필요없는 이유

0

93

2

next Request Memoization과 react cache

0

108

2

seo 최적화 기준은 데이터 fetching인가요 아님 데이터 렌더링인가요?

0

84

2

next.js 서버fetch 에러 fallback ui 구현 방법

0

173

2

프레임워크 여론 파악법

0

125

2

필터옵션이 많은 페이지에서 서버 fetch를 하는게 맞는걸까요??

0

103

2

서버 fetch suspense 로 감싸고 새로고침 시 잠시 빈 화면이 노출된 후 fallback ui가 노출됩니다.

0

102

2

template.tsx 내 서버fetch 응답값과 클라이언트 컴포넌트 상태값 싱크가 맞지 않는 이슈

0

66

2

Auth.js 사용 시 authorize 함수가 호출되지 않습니다

0

131

2

next.js 에서 로그인에 관하여

0

138

1

Next의 route handler에 대한 질문이 있습니다.

0

101

2

게시판 리스트 만들때 use client를 어디서부터 집어넣어야할지 모르겠습니다

0

97

2

프라이빗 폴더를 해야 하는 이유가 모호한 것 같아요.

0

85

2

vanilla-extract 못찾는 문제

0

229

2

fetch 캐싱과 revalidate 관련

0

84

2

강의 듣는 방법

0

104

2