React 및 JavaScript의 미래형 무한 스크롤링

현대 UX에는 무한 스크롤을 사용해야 하는 여러 사용 사례가 있습니다. 이전에는 개발자가 뷰포트와 요소의 높이를 사용하여 요소의 교차점이 뷰포트에 있는지 확인했습니다. 동일한 주요 문제는 계산이 기본 대기열에서 실행되어 앱이 약간 느려지고 약간 불안정하다는 것입니다. 며칠 전 Intersection Observer API를 접했습니다. 다음 응용 프로그램에서 사용할 수 있습니다.
  • 페이지를 스크롤할 때 이미지 또는 기타 콘텐츠를 느리게 로드합니다.
  • 사용자가 페이지를 넘길 필요가 없도록 스크롤할 때 점점 더 많은 콘텐츠가 로드되고 렌더링되는 "무한 스크롤"웹 사이트 구현.
  • 광고 수익을 계산하기 위한 광고 가시성 보고.
  • 사용자에게 결과가 표시되는지 여부에 따라 작업 또는 애니메이션 프로세스를 수행할지 여부를 결정합니다.

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

    소스 코드는 https://github.com/dhairyanadapara/infinite-scoller-example에서 사용할 수 있습니다.

    데모 링크: https://dhairyanadapara.github.io/infinite-scoller-example/

    솔루션부터 시작하겠습니다.

    import React, { Component } from "react";
    import "./App.css";
    
    class App extends Component {
        constructor(props) {
            super(props);
            this.state = {
                arr: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
            };
        }
        componentDidMount() {
            this.createObserver();
        }
    
        createObserver = () => {
            let options = {
                root: null,
                rootMargin: " 40px",
                threshold: [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0],
            };
            const boxElement = document.getElementById("loading");
            const observer = new IntersectionObserver(
                this.handleIntersect,
                options
            );
            observer.observe(boxElement);
        };
    
        handleIntersect = (entries, observer) => {
            const { arr } = this.state;
            entries.forEach((entry) => {
                console.log(entry.intersectionRatio);
                if (entry.intersectionRatio > 0) {
                    this.setState({
                        arr: arr.concat([
                            10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
                        ]),
                    });
                }
            });
        };
    
        render() {
            const { arr } = this.state;
            return (
                <div className="App" id="app">
                    <div id="infinite-container">
                        <div class="cards-list" id="card-list">
                            {arr.map((x) => (
                                <div class="card 1">
                                    <div class="card_image">
                                        {" "}
                                        <img src="https://i.redd.it/b3esnz5ra34y.jpg" />
                                    </div>
                                    <div class="card_title title-white">
                                        <p>Card Title</p>
                                    </div>
                                </div>
                            ))}
                        </div>
                        <div id="loading" style={{ height: "100px" }}>
                            Loading
                        </div>
                    </div>
                </div>
            );
        }
    }
    
    export default App;
    


    보시다시피 우리는 반응 클래스 구성 요소를 사용하여 이해하기 쉽습니다. 기능적 구성 요소를 사용할 수도 있습니다.

    옵저버 초기화에 대한 이해부터 시작하겠습니다.

    createObserver = () => {
        let options = {
            root: null,
            rootMargin: " 40px",
            threshold: [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0],
        };
        const boxElement = document.getElementById("loading");
        const observer = new IntersectionObserver(this.handleIntersect, options);
        observer.observe(boxElement);
    };
    

    IntersectionObserver는 2개의 인수를 사용합니다.

  • 옵션
    옵션은 Intersection Observer의 구성입니다. 3가지 속성이 있습니다.

  • 뿌리:
    뷰포트로 사용하려는 요소입니다. 브라우저의 뷰포트 패스null를 사용하려는 경우 .

  • 루트마진 :
    교차점을 계산하는 동안 대상 사각형에 오프셋이 추가됨

  • 한계점:
    증가하는 숫자 순서로 정렬된 임계값 목록입니다. intersectionRatio 임계값
  • 을 통과하면 콜백이 호출됩니다.



  • 콜백
    콜백에는 2개의 인수가 있습니다.

  • 항목
    대상과 루트 요소 간의 교차를 설명하는 IntersectionObserverEntry 목록

  • 관찰자
    CreateObserver에서 생성한 것과 동일한 IntersectionObserver 객체


  • 여기서 우리는 카드 목록의 맨 아래에 있을 로딩 요소를 관찰하고 있습니다. 우리의 경우 관찰자에 대상 요소가 1개뿐이므로 항목에서 1개의 객체만 얻습니다. 동일한 관찰자를 대상으로 하는 대상 요소가 여러 개인 경우 더 많은 항목을 얻게 됩니다.

    handleIntersect = (entries, observer) => {
        const { arr } = this.state;
        entries.forEach((entry) => {
            if (entry.intersectionRatio > 0) {
                this.setState({
                    arr: arr.concat([
                        10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
                    ]),
                });
            }
        });
    };
    


    IntersectionObserverEntry 객체는 boundingClientRect , intersectionRatio , intersectionRect , isIntersecting , rootBounds , target ,time .

    주요 속성은 다음과 같습니다.
  • IntersectionRatio: boundingClientRect에 대한 IntersectionRect의 백분율을 반환합니다
  • .
  • isIntersecting: 대상과 루트가 교차하는지 여부를 반환합니다.
  • target: 동일한 관찰자에게 여러 타겟이 연결되어 있을 때 중요한 속성입니다.

  • 위의 함수에서 항목을 반복하고 교차 비율이 0보다 큰지 확인했습니다. 이는 대상 요소에 루트 또는 뷰포트와의 교차가 발생했는지 여부를 의미하지 않습니다. 보시다시피 card-list 요소의 맨 아래에 있는 idloading의 요소를 관찰하고 있습니다. 따라서 아래로 스크롤하여 로딩 요소에 도달하면 교차가 발생하고 그에 따라 상태가 업데이트됩니다.

    이 경우 데이터가 빠르게 업데이트되므로 API 호출을 수행하지 않습니다. fetch 요청의 경우 rootMargin 를 사용하는 것이 좋습니다. 요구 사항에 따라 임계값을 업데이트할 수도 있습니다.

    좋은 웹페이지 즐겨찾기