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

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

๐Ÿ’™ React

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

Eun_zii 2023. 2. 14. 14:13

 

๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  { useState, useCallback, useEffect, useRef } ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ง์ ‘ ๊ตฌํ˜„ํ•ด๋ณด๊ธฐ๋กœ ํ•˜์˜€๋‹ค ! ๐Ÿฅ

์‚ฌ์šฉํ•˜๊ธฐ๋งŒ ํ•ด๋ดค์ง€ ์ง์ ‘ ๊ตฌํ˜„ํ•˜๋Š”๋ฐ์—๋Š” ๋„ˆ๋ฌด ์–ด๋ ต๊ณ  ์ดํ•ด๋„ ์ž˜ ์•ˆ๋˜์—ˆ์ง€๋งŒ 

์ •๋ณด๋„ ๋งŽ์•˜๊ณ , ๋„์›€๋„ ๋ฐ›์•„๊ฐ€๋ฉฐ ์ด๊ฒƒ ์ €๊ฒƒ ์ƒˆ๋กœ ์‹œ๋„ํ•ด๋ณด๋Š” ์žฌ๋ฏธ๋„์žˆ์—ˆ๋‹ค -๐Ÿ’™

 

๐Ÿ”† ๊ตฌํ˜„ ์ฝ”๋“œ

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

import { getPostList, postType } from "datas/postList";

const List = (): JSX.Element => {
  const [page, setPage] = useState<number>(1);
  const [posts, setPosts] = useState<postType[]>(getPostList(1));
  const ref = useRef<any>(null);

  const handleScroll = useCallback((): void => {
    const { clientHeight, scrollTop, scrollHeight } = ref.current;
    // ์Šคํฌ๋กค์„ ํ•˜๋ฉด์„œ ์‹คํ–‰ํ•  ๋‚ด์šฉ์„ ์ด๊ณณ์— ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

    if (clientHeight + scrollTop >= scrollHeight - 1) {
     // clientHeight ๊ณผ scrollTop๋ฅผ ๋”ํ•œ ๊ฐ’์ด scrollHeight - 1 ๋ณด๋‹ค ํฌ๋‹ค๋ฉด, ๊ฐ€์žฅ ์•„๋ž˜์— ๋„๋‹ฌํ–ˆ๋‹ค๋Š” ์˜๋ฏธ์ž…๋‹ˆ๋‹ค.
      setPosts(posts.concat(getPostList(page + 1)));
      // ํŽ˜์ด์ง€์— ๋”ฐ๋ผ์„œ ๋ถˆ๋Ÿฌ์˜จ ๋ฐฐ์—ด์„ posts ๋ฐฐ์—ด๊ณผ ํ•ฉ์ณ์ค๋‹ˆ๋‹ค.
      setPage((prevPage: number) => prevPage + 1);
       // ํŽ˜์ด์ง€ state ๋ณ€์ˆ˜์˜ ๊ฐ’๋„ 1์”ฉ ๋Š˜๋ ค์ค๋‹ˆ๋‹ค.
    }
  }, [page, posts]);

  useEffect(() => {
    window.addEventListener("scroll", handleScroll, true);
    // ์Šคํฌ๋กค์ด ๋ฐœ์ƒํ• ๋•Œ๋งˆ๋‹ค handleScroll ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋„๋ก ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.
    return () => {
      window.removeEventListener("scroll", handleScroll, true);
      // ํ•ด๋‹น ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์–ธ๋งˆ์šดํŠธ ๋ ๋•Œ, ์Šคํฌ๋กค ์ด๋ฒคํŠธ๋ฅผ ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค.
    };
  }, [handleScroll]);

  return (
    <Container>
      <Content ref={ref}>
        {posts.map(({ id, img, contents }: postType) => (
          <Box key={id}>
            <img src={img} alt="" />
            <Text>{contents}</Text>
          </Box>
        ))}
      </Content>
    </Container>
  );
};

const Container = styled.div`
  overflow: hidden;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  background-color: #ebebeb;
  padding-bottom: 40px;
`;
const Content = styled.div`
  max-height: 500px;
  overflow: auto;
`;
const Box = styled.div`
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;
  img {
    border-radius: 5px;
    position: relative;
    left: 10px;
  }
`;
const Text = styled.div`
  width: 295px;
  height: 45px;
  margin: 10px 0;
  background: #ffffff;
  border-radius: 5px;
  font-size: 14px;
  font-weight: 600;
  padding: 0 30px;
  display: flex;
  align-items: center;
`;

export default List;

 

export type postType = {
  id: number;
  page: number;
  contents: string;
  img: string;
};

export const getPostList = (page: number): postType[] => {
  return postList.filter((post: postType) => post.page === page);
  // ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋ฐ›์€ ํŽ˜์ด์ง€์™€ ๋™์ผํ•œ ํŽ˜์ด์ง€ ๊ฐ์ฒด๋“ค๋งŒ return ํ•ด์ค๋‹ˆ๋‹ค.
};

export const postList: postType[] = [
  {
    id: 0,
    page: 1,
    img: "http://via.placeholder.com/60x45",
    contents: "์•ˆ๋…•ํ•˜์„ธ์š” 1๋ฒˆ์งธ ๊ธ€",
  },

  {
    id: 1,
    page: 1,
    img: "http://via.placeholder.com/60x45",
    contents: "์•ˆ๋…•ํ•˜์„ธ์š” 2๋ฒˆ์งธ ๊ธ€",
  },

  {
    id: 2,
    page: 1,
    img: "http://via.placeholder.com/60x45",
    contents: "์•ˆ๋…•ํ•˜์„ธ์š” 3๋ฒˆ์งธ ๊ธ€",
  },

  {
    id: 3,
    page: 1,
    img: "http://via.placeholder.com/60x45",
    contents: "์•ˆ๋…•ํ•˜์„ธ์š” 4๋ฒˆ์งธ ๊ธ€",
  },

  {
    id: 4,
    page: 1,
    img: "http://via.placeholder.com/60x45",
    contents: "์•ˆ๋…•ํ•˜์„ธ์š” 5๋ฒˆ์งธ ๊ธ€",
  },

  {
    id: 5,
    page: 1,
    img: "http://via.placeholder.com/60x45",
    contents: "์•ˆ๋…•ํ•˜์„ธ์š” 6๋ฒˆ์งธ ๊ธ€",
  },

  {
    id: 6,
    page: 1,
    img: "http://via.placeholder.com/60x45",
    contents: "์•ˆ๋…•ํ•˜์„ธ์š” 7๋ฒˆ์งธ ๊ธ€",
  },

  {
    id: 7,
    page: 1,
    img: "http://via.placeholder.com/60x45",
    contents: "์•ˆ๋…•ํ•˜์„ธ์š” 8๋ฒˆ์งธ ๊ธ€",
  },

  {
    id: 8,
    page: 1,
    img: "http://via.placeholder.com/60x45",
    contents: "์•ˆ๋…•ํ•˜์„ธ์š” 9๋ฒˆ์งธ ๊ธ€",
  },

  {
    id: 9,
    page: 1,
    img: "http://via.placeholder.com/60x45",
    contents: "์•ˆ๋…•ํ•˜์„ธ์š” 10๋ฒˆ์งธ ๊ธ€",
  },
// ... 
]

 

๊ตฌํ˜„์€ ํ•ด๋ณด์•˜๋Š”๋ฐ ๋„ˆ๋ฌด ์–ด๋ ค์› ๋‹ค ์—ญ์‰ฌ,,๐Ÿ˜ฎ‍๐Ÿ’จ

 

๊ทธ๋ž˜๋„ ๊ฒฐ๊ณผ ๋ณด๋ฉด ๋ฟŒ๋“ฏ -โค๏ธ

728x90