[React] 무한스크롤 with ScrollEvent

이지현·2023년 9월 25일
1

react

목록 보기
2/3

들어가며

이미지 데이터를 가져와서 무한 스크롤 만들기!

본격적으로

더미 이미지 리스트 활용하기

더미 이미지를 얻기 위해서 아래 사이트를 활용합니다.
https://picsum.photos/
이미지리스트를 json형태로 불러와줍니다.

https://picsum.photos/v2/list?page=2&limit=100

fetch를 사용하여 불러오기

async function fetchImages(){
  try{
    const response = await fetch(`https://picsum.photos/v2/list`)
     
    if(!response.ok) throw new Error('network do not work');
    
    const data = await response.json();
    console.log(data);
    
  }catch(error){
    console.log(error);
  }
}

fetchImages();

비동기로 진행하기 때문에 async, await를 통해 동기적으로 실행할 수 있게 도와줍니다.

불러온 데이터를 확인합니다.

배열로 잘 넘어온 것을 확인할 수 있습니다.

이번에는 fetch().then().catch()로 바꾸어 써보았습니다.
그리고 페이지의 개수를 직접 정해서 불러올 수 있도록 함수에 인자로 넣어줍니다. 해당 page에 맞게 이미지의 일부만 불러오는 작업입니다.

export function fetchImages(page){
  const imgList = [];
  fetch(`https://picsum.photos/v2/list?page=${page}&limit=6`)
      .then((result)=>{
          return result.json();
      })
      .then((list)=>{
          imgList.push(list);
      })
      .catch((error)=>{
        console.log('error: ', error);
      })
  return imgList;
}

데이터 통신을 하는 경우 react에서는 useEffect를 사용하여 비동기로 받아옵니다.

가져온 이미지 보여주는 컴포넌트

무한 스크롤 가능 여부를 직접 불리언값으로 받아서 상황에 따라서 다르게 사용할 수 있도록 해보았습니다. 간단하게 스크롤 이벤트를 사용하여 스크롤이 끝난다면, 상태를 바꾸게 하였습니다.

import {useState, useEffect} from 'react';
import fetchImages from './fetch/image';

const ImageList = ({infinity=false}) => {
  //이미지 데이터를 받을 상태
  const [data, setData] = useState([]);
  //가져온 데이터 페이지를 관리해줄 상태
  const [page, setPage] = useState(1);
  //스크롤이 끝난 경우 true 그렇지 않으면 false
  const [isBottom, setIsBottom] = useState(false);
  
  //가장 처음에 데이터를 가져와 줍니다.
  useEffect(()=>{
  	setData(fetchImages(page));
  }. [])
  
  //처음 렌더링과 데이터가 바뀔 때, 즉, 데이터가 없는 순간은 true의 값을 가집니다. 데이터가 바뀌면 스크롤이 더 생기며 isBottom은 false가 됩니다.
  useEffect(()=>{
    const handleScoll = ()=>{
    	setIsBottom(window.innerHeight + document.documentElement.scrollTop + 5) >= document.documentElement.offsetHeight)
    }
  	window.addEventListener('scroll', handleScoll);
    
    return ()=>{
    	window.removeEventListener('scroll', handleScoll);
    }
  }, [data])
  
  //페이지가 바뀔 때 데이터를 추가로 가져옵니다.
  useEffect(()=>{
    setData((prevData)=>(...prevData, ...fetchImages(page)));
  },[page]);
  
  //무한 스크롤 설정을 하였고, 스크롤이 끝난다면 페이지를 1씩 올려줍니다.
  useEffect(()=>{
    if(infinity && isBottom) setPage((prev) => prev + 1)
  },[isBottom])
  
  return(
    <div>
      {data.map((img, key)=>{
      	return <li key={`img_${key}`}><img src={img.url} alt={img.author} /></li>
      })}
    </div>
  )
};
      
export default ImageList;

직접 사용하기

import ImageList from './components/ImageList'

function App(){
  return (
  	<ImageList infinity={true} />
  )
}

결론

useEffect의 의존 배열을 사용하여 상태가 변할 때 어떤 게 실행이 될지 확실하게 생각을 정리하고 적용해야겠습니다. 직접 코드를 써보고 수업 내용을 보면서 또 덮어서 쓰고 하는데, 이번건 거의 수업 내용을 따라서 쳐본 걸로 되었습니다. 프로젝트에 무한 스크롤을 적용해보면서 몇 번 더 연습해야 할 듯 합니다.

profile
건축학도의 프론트엔드 개발자 되기

0개의 댓글