๐Ÿค ์€์ง€log ๐Ÿค

[REACT] Infinite scroll (๋ฌดํ•œ์Šคํฌ๋กค) ๊ตฌํ˜„ํ•˜๊ธฐ ๋ณธ๋ฌธ

๐Ÿ’™ React

[REACT] Infinite scroll (๋ฌดํ•œ์Šคํฌ๋กค) ๊ตฌํ˜„ํ•˜๊ธฐ

Eun_zii 2023. 10. 13. 14:21

 

๊ธฐ์กด์— NodeJS๋กœ ๋งŒ๋“ค์–ด๋‘” ์„œ๋ฒ„์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ get ํ•ด์™€์„œ ํ”„๋ก ํŠธ์—์„œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ์ง์ ‘ ๋ฌดํ•œ์Šคํฌ๋กค์„ ๊ตฌํ˜„ํ•ด๋ณด์•˜๋‹ค.

์˜ˆ์ „์— ํ•ด๋ดค๋˜๊ฑด๋ฐ ๋‹ค์‹œ ํ•˜๋ ค๋‹ˆ ํ—ท๊ฐˆ๋ฆฌ๊ธฐ ์‹œ์ž‘ ...๐Ÿ˜ต‍๐Ÿ’ซ ; ๊ทธ๋ž˜๋„ ์–ด์ฐŒ์–ด์ฐŒ ๊ตฌํ˜„์€ ํ•ด๋ณด์•˜๋‹ค .. 

์Šคํฌ๋กค์ด ์›€์ง์ด๋ฉด ๋ฐ์ดํ„ฐ๋ฅผ ๊ณ„์† ํ•ด์„œ ๋ถˆ๋Ÿฌ์˜จ๋‹ค.

( + ์Šคํฌ๋กค์ด ๋ฐ”๋‹ฅ์— ๋‹ฟ์œผ๋ฉด ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋Š” ์ฝ”๋“œ๋„ ๊ตฌํ˜„์˜ˆ์ •)

 

// useGetFruits.ts
import axios from "axios";
import { useInfiniteQuery } from "react-query";

const fetchFruits = async () => {
  const { data } = await axios.get(`http://localhost:8080/fruits`);
  return data;
};

const useGetFruits = () => {
  return useInfiniteQuery("fruits", fetchFruits, {
    getNextPageParam: (lastPage, allPages) => {
      if (lastPage.length > 0) return undefined;
      return allPages.length + 1;
    },
  });
};

export default useGetFruits;

 

// Main.tsx

import { useCallback, useEffect, useRef, useState } from "react";
import styled from "styled-components";

import useGetFruits from "src/api/useGetFruits";
import Fruit from "src/templates/Fruit";
import { FruitType } from "src/types/Fruit";

const Main = () => {
  const { data, fetchNextPage, hasNextPage, isFetchingNextPage } =
    useGetFruits();
  const [loadData, setLoadData] = useState(false);
  const ref = useRef<any>(null);

  const handleScroll = useCallback(() => {
    const { clientHeight, scrollTop, scrollHeight } = ref.current;
    if (
      clientHeight + scrollTop >= scrollHeight - 1 &&
      hasNextPage &&
      !isFetchingNextPage
    ) {
      setLoadData(true);
    }
  }, [hasNextPage, isFetchingNextPage]);

  useEffect(() => {
    if (loadData) {
      fetchNextPage();
      setLoadData(false);
    }
  }, [loadData, fetchNextPage]);

  useEffect(() => {
    if (ref.current) {
      window.addEventListener("scroll", handleScroll, true);
    }

    return () => {
      if (ref.current) {
        window.removeEventListener("scroll", handleScroll, true);
      }
    };
  }, [handleScroll]);

  return (
    <Container>
      <Title>๐Ÿ Infinite_Scroll ๐Ÿ</Title>
      <List ref={ref}>
        {data &&
          data.pages.map((pageData) =>
            Array.isArray(pageData)
              ? pageData.map((fruit: FruitType) => (
                  <Fruit key={fruit.id} fruit={fruit} />
                ))
              : null
          )}
      </List>
    </Container>
  );
};

const Container = styled.div`
  display: flex;
  justify-content: center;
  align-items: center;
  flex-direction: column;
  text-align: center;
`;

const Title = styled.h2`
  font-size: 50px;
`;

const List = styled.div`
  margin: 20px 0 0;
  font-size: 35px;
`;

export default Main;

 

728x90