인프런 커뮤니티 질문&답변

김용민님의 프로필 이미지
김용민

작성한 질문수

Next + React Query로 SNS 서비스 만들기

인피니트 스크롤링

무한스크롤 구현시 발생하는 문제

작성

·

546

·

수정됨

0

스크린샷 2024-01-23 오후 9.06.06.png강의 수강중에, 배운 무한스크롤을 바탕으로 개인 프로젝트를 진행중입니다.
위의, 데이터를 받아오는 것을 보면, 처음에는 2개를 불러오고, 그 이후에는 계속 5개를 불러오는데, 제가 원하는 방식은 처음부터 끝까지 5개씩 계속 일정하게 불러오는 것을 원합니다. 이유를 찾을려고 여러가지 검색을 해보며 해봤는데도, 해결되지않아서 질문드립니다. 이 경우 의심해볼 수 있는 부분은 어떤 부분이 있을까요?

최상위 페이지에서 아래와 같이 prefetch를 해오고

type HomeProps = {
  params: {
    category: string;
  };
};

const CategoryDetailPage: React.FC<HomeProps> = async ({ params }) => {
  const { category } = params;

  const queryClient = new QueryClient();
  const college = category;

  // 서버에서 불러온 데이터를 클라이언트의 리액트 쿼리가 물려받음.(하이드레이트)
  await queryClient.prefetchInfiniteQuery({
    queryKey: ['posts', college],
    queryFn: ({ pageParam = 1 }) => getFilteredPosts(college, { pageParam }), // searchParams 전달
    // 커서 값
    initialPageParam: 0
  });

  // hydrate라는 것은 서버에서 온 데이터를 클라이언트에서 그대로, 물려받는 것 이다.
  const dehydratedState = dehydrate(queryClient);

  return (
    <HydrationBoundary state={dehydratedState}>
      <Container>
        <ListingContainerTest />
      </Container>
    </HydrationBoundary>
  );
};

export default CategoryDetailPage;

실제 무한스크롤을 사용하는 곳은 아래와 같이 사용하고 있습니다.

'use client';

import { getFilteredPosts } from '@/app/lib/getFilteredPosts';
import { useInfiniteQuery } from '@tanstack/react-query';
import { usePathname } from 'next/navigation';
import { Fragment, useEffect } from 'react';
import { useInView } from 'react-intersection-observer';
import ClimbingBoxLoader from 'react-spinners/ClimbingBoxLoader';

import EmptyState from '../EmptyState';
import ListingGrid from './ListingGrid';

const ListingCard = () => {
  const path = usePathname();
  // ['', chss]
  const college = path.split('/')[1];

  const {
    data: listings,
    fetchNextPage,
    hasNextPage,
    isFetching,
    isError
  } = useInfiniteQuery({
    queryKey: ['posts', college],
    queryFn: ({ pageParam = 1 }) => getFilteredPosts(college, { pageParam }),
    initialPageParam: 0,
    // 가장 최근에 불러왔던 게시글
    getNextPageParam: (lastPage) => lastPage.studyList.at(-1)?.id,
    staleTime: 60 * 1000,
    gcTime: 300 * 1000
  });
  // lastPage.jobList.at(-1)?.id,
  const { ref, inView } = useInView({
    // div가 보이고나서 몇픽셀 정도의 이벤트가 호출될 것 인가? 보이자마자 바로 호출.그래서0
    threshold: 0,
    // 몇초후에 딜레이 보일것인지.
    delay: 0
  });

  console.log(listings);

  useEffect(() => {
    if (inView) {
      !isFetching && hasNextPage && fetchNextPage();
    }
  }, [inView, isFetching, hasNextPage, fetchNextPage]);

  if (isError || listings?.pages?.length === 0) {
    return <EmptyState />;
  }

  return (
    <>
      <div className="pt-24 grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5 2xl:grid-cols-6 gap-8">
        {listings?.pages.map((page) =>
          // Assuming each page has a 'studyList' property
          page.studyList.map((listing: any) => (
            <Fragment key={listing.id}>
              <ListingGrid data={listing} />
            </Fragment>
          ))
        )}
        <div ref={ref} style={{ height: 50 }}></div>
      </div>

      {isFetching && (
        <div className="flex items-center justify-center">
          <ClimbingBoxLoader color="#36d7b7" size={20} />
        </div>
      )}
    </>
  );
};
export default ListingCard;

 

답변 1

0

제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

네트워크 탭에서 요청에 대한 response을 볼 때도 처음에는 두 개만 불러오나요? 서버에서 두 개만 주는 건가요?

김용민님의 프로필 이미지
김용민
질문자

imageimageimage이렇게 받아오는 것 같습니다.
제가 원하는건 첫 화면에 아래 이미지에 jobList와 studyList의 5개의 데이터를 받아오고 싶은데, 첫번째 데이터가 0, 1 총 2개밖에없어서 현재 2개밖에 안나오는 상황입니다.image현재 아래코드와 같이 캐시된 데이터를 갖고, 데이터를 받아와서, 카테고리 화면을 꾸려주고 있습니다.

import { useQueryClient } from '@tanstack/react-query';
import { usePathname } from 'next/navigation';

import ListingGrid from '../listings/ListingGrid';

type CategoryAllProps = {
  onClick: (value: string) => void;
};

const CategoryAll = ({ onClick }: CategoryAllProps) => {
  const path = usePathname();
  const college = path.split('/')[1];
  const cache = useQueryClient();
  const data = cache.getQueryData(['posts', college]);
  const jobList = data.pages[0].jobList;
  const studyList = data.pages[0].studyList;

  console.log(data);

  return (
    <div className="flex flex-col gap-12 mt-10">
      <div className="flex flex-col gap-6 shadow-md p-8 rounded-md border-[1px] border-gray-100">
        <div className="font-bold text-gray-700 text-xl">스터디 · 프로젝트 모집</div>
        <div className="flex flex-row gap-2 flex-wrap">
          {studyList.map((studyData: any, index: any) => (
            <ListingGrid key={index} data={studyData} />
          ))}
        </div>
        <div
          className="flex font-md text-gray-500 text-sm cursor-pointer ml-auto"
          onClick={() => onClick('study')}>
          더 보기
        </div>
      </div>
      <div className="flex flex-col gap-6 shadow-md p-6 rounded-md border-[1px] border-gray-100">
        <div className="font-bold text-gray-700 text-xl">취업 정보 교류</div>
        <div className="flex flex-row gap-2 flex-wrap">
          {jobList.map((jobData: any, index: any) => (
            <ListingGrid key={index} data={jobData} />
          ))}
        </div>
        <div
          className="font-md text-gray-500 text-sm cursor-pointer ml-auto"
          onClick={() => onClick('info')}>
          더 보기
        </div>
      </div>
    </div>
  );
};

export default CategoryAll;
제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

네, 그러니까 왜 서버가 2개만 주나요? 서버쪽 코드는 제가 모릅니다. 프론트에서 요청을 잘못해서 서버에서 2개만 주는 거 아닌가요?

prefetchQuery의 queryFn에 넣은 함수에서 지금 서버쪽에 2개만 받아오도록 하고있는 것 같습니다. 그 요청을 알아야합니다.

pageParam = 1 을 주신 것도 의심가는 부분입니다. pageParam은 기본값이 0인데 그걸 다시 1로 바꾸시는 이유가 뭔가요?

김용민님의 프로필 이미지
김용민

작성한 질문수

질문하기