본문 바로가기
JavaScript/React

[React] 무한 스크롤 Infinite Scroll 구현하기

by dev또리 2023. 4. 25.
728x90

 

 infinite(=무한)를 구현하는 infinite.jsx와 그를 불러오는 infiniteLanding.jsx로 나뉜다.

 

infinite.jsx

 

import React, {useEffect, useState} from 'react'
import Card from '../utils/card/card';

const Infinite = ({posts, fetching, fetchMoreData}) => {

  const [postInfo, setPostInfo] = useState([]);

  useEffect(() => {
    setPostInfo(posts);
  }, [posts])

  const handleScroll = () => {
    const scrollHeight = document.documentElement.scrollHeight;
    const scrollTop = document.documentElement.scrollTop;
    const clientHeight = document.documentElement.clientHeight;

    if(scrollTop + clientHeight >= scrollHeight && fetching === false) {
fetchMoreData();
}
    }

  useEffect(() => {
    window.addEventListener('scroll', handleScroll);
      return () => {window.removeEventListener('scroll', handleScroll)
}
  })
    return (
      <div>
        { postInfo && postInfo.map((post, idx) => (
           <Card key={idx} listInfo={post} />
        ))}
      </div>
  )
}

export default Infinite;

postInfo의 값이 들어와있는 상태를 체크하기 위해 postInfo &&를 먼저 조건으로 주었고,

useEffect에서 scroll event를 더하는 것이다.

 

 

 

infiniteLanding.jsx

import React, {useState, useEffect} from 'react'
import axios from 'axios'
import Infinite from './sections/infinite'

const InfiniteLanding= () => {

  const [listInfo, setListInfo] = useState([]);
  const [skip, setSkip] = useState(0);
  const [limit, setLimit] = useState(10);
  const [fetching, setFetching] = useState(false);

  useEffect(() => {

    const body = {
      skip: skip,
      limit: limit,
    };
    getData(body)
    }, [])

  const getData = (body) => {
    axios.post("/api/url", body)
      .then( res => {
         if(body.loadMore) setListInfo([...listInfo, ...res.data.listInfo]);
         else setListInfo(res.data.listInfo)
           })
      .catch(err => alert("글을 가져오는데 실패 했습니다.");)
  }

  const fetchMoreData = () => {
    setFetching(true);
    let tmpSkip = skip + limit
    let body = {
      skip: tmpSkip,
            limit: limit,
            filters: filters,
            loadMore: true
        };

        getData(body);
        setSkip(tmpSkip);
        setFetching(false);
    }


    return (
      <div>
        <h2>TITLE</h2>
      <div>
        <Infinite posts={listInfo} fetchMoreData={fetchMoreData} fetching={fetching}/>
      </div>
    )
}

export default InfiniteLanding;

 

 

728x90

댓글