이미지 데이터를 가져와서 무한 스크롤 만들기!
더미 이미지를 얻기 위해서 아래 사이트를 활용합니다.
https://picsum.photos/
이미지리스트를 json형태로 불러와줍니다.
https://picsum.photos/v2/list?page=2&limit=100
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
의 의존 배열을 사용하여 상태가 변할 때 어떤 게 실행이 될지 확실하게 생각을 정리하고 적용해야겠습니다. 직접 코드를 써보고 수업 내용을 보면서 또 덮어서 쓰고 하는데, 이번건 거의 수업 내용을 따라서 쳐본 걸로 되었습니다. 프로젝트에 무한 스크롤을 적용해보면서 몇 번 더 연습해야 할 듯 합니다.