본문 바로가기
React TIL

[React] Day_52 데일리 정리

by 림졍 2024. 12. 2.
728x90
반응형

 

돌려줘요 내 시간

 

이리뛰랴 저리뛰랴 바빴던 오늘

딱히 뭐 한게 없는데 하루가 왜 다.. 가버렸지?

여튼 오늘은 실습하기 전.. 간단하게 강의정리좀 해보겠습니다

가보자고.

 

챌린지반 강의정리 - 페이지네이션, 무한스끄롤

아, 이게 페이지네이션이었군!

너란 놈은 무서운 애야!

 

useInfiniteQuery

TanStack Query에서 제공하는 무한스크롤 및 페이지네이션 구현용 훅

데이터를 페이지 단위로 가져오고 효율적으로 캐싱하며 상태 관리 지원

 

특징

  • data.pages: 페이지 단위 데이터를 배열에 누적 저장
  • fetchNextPage: 다음 페이지 데이터 요청 함수
  • 페이지네이션과 무한스크롤 모두 구현 가능
  • API의 응답에 따라 nextPage 필드로 다음 페이지 관리

 

응답 데이터 구조

 

- 필수

  • data: 현재 페이지 데이터 배열
  • nextPage: 다음 페이지 번호 (없으면 null 반환)

- 선택

  • totalPages: 전체 페이지 수
  • totalItems: 전체 데이터 수

 

- 예제

// 기본 API 응답 예시
{
  "data": [ { "id": 1, "title": "Photo 1" }, { "id": 2, "title": "Photo 2" } ],
  "nextPage": 2
}

// 다음 페이지가 없을 경우
{
  "data": [ { "id": 21, "title": "Photo 21" } ],
  "nextPage": null
}

 

사용법

 

- 기본 페이지네이션

import { useInfiniteQuery } from "@tanstack/react-query";

const fetchPhotos = async ({ pageParam = 1 }) => {
  const response = await fetch(`https://api.example.com/photos?page=${pageParam}`);
  const result = await response.json();
  return { data: result.data, nextPage: result.nextPage };
};

const Pagination = () => {
  const { data, fetchNextPage, hasNextPage, isLoading } = useInfiniteQuery({
    queryKey: ["photos"],
    queryFn: fetchPhotos,
    getNextPageParam: (lastPage) => lastPage.nextPage,
  });

  if (isLoading) return <div>Loading...</div>;

  return (
    <div>
      {data.pages.map((page) => (
        <div key={page.id}>
          {page.data.map((photo) => <p key={photo.id}>{photo.title}</p>)}
        </div>
      ))}
      {hasNextPage && <button onClick={fetchNextPage}>Load More</button>}
    </div>
  );
};

 

 

IntersectionObserver

요소가 화면에 보이는지 비동기로 감지하여 효율적으로 스크롤 상태를 관리하는 API!

요소 감지 시, 데이터를 추가 요청하거나 로드를 실행 가능

 

 

사용법

import { useRef, useEffect } from "react";

const InfiniteScrollExample = ({ fetchMoreData }) => {
  const observerRef = useRef();
  
  useEffect(() => {
    const observer = new IntersectionObserver(
      ([entry]) => {
        if (entry.isIntersecting) fetchMoreData();
      },
      { threshold: 1.0 }
    );
    
    if (observerRef.current) observer.observe(observerRef.current);
    return () => observer.disconnect();
  }, [fetchMoreData]);
  return <div ref={observerRef} style={{ height: "20px", background: "gray" }} />;
};

 

 

useInfiniteQuery + IntersectionObserver

 

페이지네이션과 무한스크롤 모두 해결 가능!

무한스크롤로 대용량 데이터를 처리하며 성능까지 챙길 수 있ㄷr... 오...오진다아..

import { useInfiniteQuery } from "@tanstack/react-query";
import { useRef, useEffect } from "react";

const fetchPhotos = async ({ pageParam = 1 }) => {
  const response = await fetch(`https://api.example.com/photos?page=${pageParam}`);
  const result = await response.json();
  return { data: result.data, nextPage: result.nextPage };
};

const InfiniteScroll = () => {
  const { data, fetchNextPage, hasNextPage, isLoading } = useInfiniteQuery({
    queryKey: ["photos"],
    queryFn: fetchPhotos,
    getNextPageParam: (lastPage) => lastPage.nextPage,
  });
  
  const observerRef = useRef();

  useEffect(() => {
    const observer = new IntersectionObserver(
      ([entry]) => {
        if (entry.isIntersecting && hasNextPage) fetchNextPage();
      },
      { threshold: 1.0 }
    );

    if (observerRef.current) observer.observe(observerRef.current);
    
    return () => observer.disconnect();
  }, [fetchNextPage, hasNextPage]);

  if (isLoading) return <div>Loading...</div>;

  return (
    <div>
      {data.pages.map((page) => (
        <div key={page.id}>
          {page.data.map((photo) => <p key={photo.id}>{photo.title}</p>)}
        </div>
      ))}
      <div ref={observerRef} style={{ height: "20px", background: "lightgray" }}>Scroll down</div>
    </div>
  );
};

 

 

마무리 - 오늘은 노래를 준비했습니다.. (ft. 건달)

 

 

 

뼈를깎는 고통을 통해 오늘 tanstackquery를 성공적으로 구현했다!

그리고 개 펑펑 울었다.. 못하는 내 자신이 한심해서 어헝헝...

맘속으로 개발자 접을까 오지게 생각하고 있었는데

지금 잘 하고 있는거라고 마음써주신 다른분들께 너무 죄송스럽고.. 감사하달까

오늘 건달이 추천해준 노래들으면서 자러가야겄다.

민나 굳바2.

 

728x90
반응형