본문 바로가기
React

React 무한스크롤 Intersection Observer API

by Rogan_Kim 2022. 12. 18.
728x90

 

 

CRA에서 간단하게 Intersction Observer API를 사용한 무한스크롤 방법을 기록 하였습니다.

 

 

 

우선 공식문서에 나온 Intersection Observer API 사용방법 입니다.

 

options는 어떻게 설정하면 되는지 설명해 드리겠습니다.

const options = {
  root: document.querySelector('#scrollArea'),
  rootMargin: '0px',
  threshold: 1.0
}

const observer = new IntersectionObserver(callback, options);

 

root는 viewport를 지정해주면 됩니다.

 

Intersection Observer API 공식문서 첫 문장을 보면 나오는 설명입니다.

Intersection Observer API는 상위 요소 또는 최상위 문서의 뷰포트 와 대상 요소의 교차에서 변경 사항을 비동기식으로 관찰하는 방법을 제공합니다 . 

 

나중에 지정해줄 타겟인 관찰자를 root(viewport)안에 있는지 없는지를 확인해주는 방법이라고 생각하면 됩니다.

 

rootMargin은 viewport의 margin입니다.

 

주의할 점은 이 속성은 css margin이랑 좀 다릅니다.

저는 해당 속성을  padding이라고 생각하고 접근하면 좀 편하지 않을까 싶습니다.

 

margin을 '0px 0px 100px 0px'을 주게 되면, viewport의  관찰범위를  아래로 100px만큼  늘려 주는 것입니다.

처음에 이속성을 조작하다가 'left right는 만질일이 없지 않나?' 싶었는데, viewport width값이 관찰자의 width보다 작을때,

해당 요소가 화면에 100% 보여지지 않는다고 판단하는데 이런 경우에 'left, right를 조절하여 100%보여지게 끔 설정 할 수 있습니다.

 

 

threshold쓰임이 유용합니다.

viewport에 관찰대상이 통과하는 시점이 있는데,  이떄 callback함수가 실행됩니다. 

1.0을 넣으면, 화면에 다 보여질때, 실행이됩니다.

근데 만약 위에 margin에서 말했듯이 viewport안에 관찰자가 다 보여줘야하는데 width값이 viewport가 관찰자 보다 더 작으면 통과했다고 판단 안합니다. 

threshold는 1.0외에 배열을 받는데, [0, 0.25, 0.5, 0.75, 1]을 주게 되면, 25%가 더 보여지는 시점에 callback을 실행시켜줍니다.

1%보여질때마다 callback을 실행 시킬려면 배열을 [0.1, 0.2, ...., 1] 이렇게 넣어주면됩니다.

 

 

여기까지 간단히 option을 알아 보았습니다. 

저는 Intersection Observer API로 react-catbow-scrollview 를 만들어 배포한 경험이 있습니다.

이때, 해당 option에대해 여러가지 테스트를 많이 해봐서 경험이 있습니다.

궁금한 점은 댓글로 남겨주시면, 알려드리겠습니다.

 

GitHub - catbow/react-catbow-scrollview

Contribute to catbow/react-catbow-scrollview development by creating an account on GitHub.

github.com

 

 

 

 

본격적으로 React에  사용하기 무한스크롤 편

 

따라 하면서 익힐 수 있도록 기본 틀을 제공해 드리겠습니다.

 

style.css

.container {
	position: absolute;
	top: 0;
	left: 0;
	right: 0;
	bottom: 0;
	display: flex;
	gap: 5px;
	flex-direction: column;

	align-items: center;
	width: 500px;
	height: 800px;
	margin: auto;

	border: 1px solid black;
	overflow: scroll;
}

.box {
	width: 300px;
	height: 300px;
	border: 1px solid gray;
}

 

 

data.json

[
  "https://cdn.pixabay.com/photo/2022/09/05/10/36/grey-seal-7433843_1280.jpg",
  "https://cdn.pixabay.com/photo/2022/06/21/22/48/flower-7276636_1280.jpg",
  "https://cdn.pixabay.com/photo/2022/09/11/05/22/pelican-7446158_1280.jpg",
  "https://cdn.pixabay.com/photo/2012/03/01/00/55/flowers-19830_1280.jpg",
  "https://cdn.pixabay.com/photo/2016/06/13/07/32/cacti-1453793_1280.jpg"
]

 

 

App.js

import { useState, useRef } from 'react';

import mockData from '.data.json';

import './style.css';

function App() {
  const [data, setData] = useState([]);
  
  const viewport = useRef(null);
  const observeRef = useRef(null);
  
  const observerOn = useRef(false);
  
  useEffect(() => {
  const option = {
    root: viewport.current,
  };

  const observer = new IntersectionObserver(entries => {
    entries.forEach(entry => {
	  if (entry.isIntersecting) {
	    setTimeout(() => {
		  setData(prev => [...prev, ...mockData]);
		}, 500);
	  }
	});
  }, option);

  if (!observerOn.current) {
	observerOn.current = true;
	observer.observe(observeRef.current);
  }
}, []);

  return (
    <div className='container' ref={viewport}>
      {data.map((one, idx) => (
        <img className='box' key={idx} src={one} alt='그림들' />
      ))}
      <div ref={observeRef} />
    </div>
  );
}

export default App;

 

mockData와 css위치에 따른 import 확인 해주시고,

그럴리는 없지만 react 버전으로 인한 'import React'도 확인 해주시고 따라 오시면 됩니다.

 

저는 Intersection Observer API를 사용하여 무한 스크롤을 구현할때, clean up 처리를 안해도 된다고 생각하고 있습니다.

window의 scroll에 이벤트를 주는 것도 마찬가지입니다.

그 이유로는  clean up을 사용하는 이유는 이벤트가 중첩이 되는 것을 막기 위해서 인데, 반대로 생각하여,

'한번만 넘겨주면 되지 않나?' 라는게 제 주장입니다.

실제로 많은 경우의 수를 테스트 해봤을때도 문제 없고, 함수를 보내 줄때, 해당 이벤트가 이미 있는지 없는지도 확인하는 로직을

작성하면, 중첩될 일이 없다고 봅니다.

라이브러리 react-catbow-scrollview도 해당 방식으로 구현 되어있습니다.

다른 의견이 있으시거나 허점이 보이시면 알려 주시면 감사합니다.

 

 

 

728x90

'React' 카테고리의 다른 글

React 드래그 앤 드롭으로 puzzle-game 만들기  (0) 2022.12.19

댓글