무한 스크롤 - infinite scrollFrontend/UI&UX2022. 6. 11. 01:48
Table of Contents
How - useInview
- 무한 스크롤을 스크롤 이벤트를 통해서 구현하기도 하고 여러 방법이 있겠지만 react-intersection-observer의 useInView 훅을 사용해 쉽게 구현할 수 있다.
yarn add react-intersection-observer
- useInView의 첫번째 파라미터로 ref를 설정할 수 있고 두번째 파라미터는 ref가 걸린 요소가 화면에 보이면 true로 값이 변경되고 화면에 보이지 않으면 false로 변한다
const [ref, isView] = useInView()
- 아래 예시를 살펴보자!
- 맨 아래 요소에 ref를 걸고 useEffect를 이용해서 맨 아래 요소가 화면에 보이는 여부에 따라 isView가 변경될 때마다 콘솔에 isView를 출력해보자!
import { useInView } from "react-intersection-observer"
import styled from "styled-components";
import {useEffect} from "react";
const App = () => {
const [ref, isView] = useInView()
useEffect(()=>{console.log(isView)}, [isView])
return(
<>
<Data>Data</Data>
<Data>Data</Data>
<Data>Data</Data>
<Data>Data</Data>
<Data ref={ref}>Data</Data>
</>
);
}
const Data = styled.div`
height: 300px;
font-size: 30px;
border: 2px solid black;
margin: 20px;
`
export default App;
- 맨 아래 요소가 보이면 true로 isView가 변경되고 보이지 않으면 false로 변경된다!
무한 스크롤 구현
- 서버에 아래같은 데이터가 200개 정도 있고 한 페이지에서 데이터를 3개 보내준다고 가정하자
"people": [
{
"name": "aaa"
},
...
]
- 마지막으로 불러온 데이터에 useInView의 ref를 달아두고 마지막 요소가 보여서 useEffect를 사용해서 isView가 true가 될 때만 데이터를 불러와서 데이터를 담고 있는 data 상태에 추가하고 page 상태를 1 증가시킨다.
- 맨 처음에 데이터를 한번 불러오는 이유는 ref를 붙일 요소가 없기 때문이다!
- isView가 계속 false라 데이터를 안부르겠지?
import {useInView} from "react-intersection-observer"
import styled from "styled-components";
import {useEffect, useState, useCallback} from "react";
import axios from "axios";
const App = () => {
const [ref, isView] = useInView();
const [page, setPage] = useState(1);
const [data, setData] = useState([]);
const getData = useCallback(async () => {
// 서버에서는 한 페이지당 3개의 데이터를 보내준다
await axios.get(`http://localhost:5008/people?_page=${page}&_limit=3`)
.then((res) => {
// 기존 데이터에 새로 불러온 데이터를 합치고 page를 + 1시킴
setData([...res.data, ...data]);
setPage(page + 1);
})
}, [isView])
// 맨 처음 렌더링 되었을 때 데이터를 한번 불러옴!
useEffect(() => {
getData();
}, [])
// isView가 true 일 때만 데이터를 불러옴!
// 보였다 안보이면 true에서 false로 바뀌기 때문에 useEffect가 두번 실행됨!
useEffect(() => {
if (isView) {
getData();
}
}, [isView])
return (
<>
{data.map((item, idx) => (
<div key={idx}>
{data.length - 1 === idx ? (
// 맨 마지막 요소에 ref
<Data ref={ref}>{item.name}</Data>
) : (
<Data>{item.name}</Data>
)}
</div>
))}
</>
);
}
const Data = styled.div`
height: 300px;
font-size: 30px;
border: 2px solid black;
margin: 20px;
`
export default App;
'Frontend > UI&UX' 카테고리의 다른 글
react-dnd → Drag & Drop (1) | 2022.06.30 |
---|---|
tailwind-css (0) | 2022.06.11 |
이미지 업로드, 미리보기 (0) | 2021.11.19 |
react-toastify (0) | 2021.09.29 |
Swiper 만들기 (0) | 2021.08.30 |
@덕구공 :: Duck9s'
주니어 개발자에욤
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!