Intersection Observer API를 사용한 무한 스크롤

개시하다


Intersection Observer API를 사용하여 맨 아래로 스크롤한 후 다음 내용을 읽고 표시하는 무한 스크롤을 구현했기 때문에 그 기록을 썼습니다.
문장용 코드이기 때문에 jsonplaceeholder에서 데이터를 얻었습니다.
https://jsonplaceholder.typicode.com/
교차 관찰자 API(Intersection Observer API)는 이곳을 참고했다.이곳의 설명은 생략되었으니, 만약 이해하지 못하는 부분이 있으면 제때에 이 보도를 읽어 주십시오.
https://developer.mozilla.org/ja/docs/Web/API/Intersection_Observer_API
loading과 error의 처리는 이번에 생략되었습니다...(・)
사용자 정의 스크립트로 논리 부분을 분리하지 않았습니다.(・)

액션


이런 느낌이에요.ScrollObserver 구성 요소는 알기 쉬운 빨간색을 배경으로 하고, 이 구성 요소가 교차하면 함수가 실행됩니다

전역 코드


App.jsx
import { useCallback, useEffect, useState } from "react";

import "./App.css";
import { ScrollObserver } from "./ScrollObserver";

function App() {
  const [todos, setTodos] = useState([]);
  const [isActiveObserver, setIsActiveObserver] = useState(true);

  const fetchTodos = useCallback(async () => {
    const res = await fetch(
      "https://jsonplaceholder.typicode.com/todos?_limit=10"
    );
    const json = await res.json();
    setTodos(json);
  }, []);

  useEffect(() => {
    fetchTodos();
  }, [fetchTodos]);

  const fetchNextTodos = useCallback(async () => {
    const res = await fetch(
      `https://jsonplaceholder.typicode.com/todos?_start=${todos.length}&_limit=10`
    );
    const json = await res.json();
    // データをすべて取得したとき
    if (json.length === 0) {
      return setIsActiveObserver(false);
    }
    setTodos([...todos, ...json]);
  }, [todos]);

  return (
    <div className="App">
      <h1>無限スクロール</h1>
      <div className="container">
        <ol>
          {todos.map((todo) => {
            return <li key={todo.id}>{todo.title}</li>;
          })}
        </ol>
        <ScrollObserver
          onIntersect={fetchNextTodos}
          isActiveObserver={isActiveObserver}
        />
      </div>
    </div>
  );
}

export default App;

ScrollObserver.jsx
import { memo, useEffect, useRef } from "react";

export const ScrollObserver = memo((props) => {
  const { onIntersect, isActiveObserver } = props;
  const ref = useRef(null);

  useEffect(() => {
    const observer = new IntersectionObserver(
      (entries, observer) => {
        if (entries[0].intersectionRatio >= 1) {
          observer.disconnect();
          onIntersect();
        }
      },
      {
        threshold: 1,
      }
    );
    observer.observe(ref.current);
  }, [onIntersect]);

  return (
    <>
      {isActiveObserver ? (
        <div ref={ref} style={{ height: "50px", backgroundColor: "red" }}>
          <p>読み込み中...</p>
        </div>
      ) : null}
    </>
  );
});

코드 해설


초기 데이터 가져오기


우선 우리는 먼저 10개의 데이터를 얻었다.
App.jsx
  const fetchTodos = useCallback(async () => {
    const res = await fetch(
      "https://jsonplaceholder.typicode.com/todos?_limit=10"
    );
    const json = await res.json();
    setTodos(json);
  }, []);

  useEffect(() => {
    fetchTodos();
  }, [fetchTodos]);

교차를 만들 때 실행할 함수


이것은 ScrollObserver 구성 요소에 전달되는 함수를 통해 교차할 때 처리하고자 하는 것입니다.todos에서 배열한 마지막 10개의 검색 매개 변수가 적혀 있습니다.의존 배열에 토토스가 있는 것은 토토스의 값이 토토스를 바꾸었기 때문이다.length의 길이도 바뀌기 때문에 기록 값을 다시 계산하고 있습니다.가져올 데이터가 없어도 ScrollObserver의 감시 상태가 계속되기 때문에 데이터를 얻은 후 isActiveObserver를 가짜로 설정하고 ScrollObserver 구성 요소의 되돌아오는 값을 비워 두십시오.이 근처에서 간결하게 쓸 수 있을지 궁금하니 조언이 있으면 메시지를 남겨 주세요.
App.jsx
  const fetchNextTodos = useCallback(async () => {
   const res = await fetch(
     `https://jsonplaceholder.typicode.com/todos?_start=${todos.length}&_limit=10`
   );
   const json = await res.json();
   // データをすべて取得したとき
   if (json.length === 0) {
     return setIsActiveObserver(false);
   }
   setTodos([...todos, ...json]);
 }, [todos]);

ScrollObserver 구성 요소


이것은 props에서 교차할 때 실행하고 싶은 함수 (이번에는fetchNextTodos) 와boolean의 isActive Observer입니다.
useRef는 관찰자를 창설한 후 감시의 목표 요소를 제공해야 하기 때문에 사용한다.useRef의 상세한 내용은 공식 문서를 참고하십시오.
https://ja.reactjs.org/docs/hooks-reference.html#useref
교차할 때의 처리는 IntersectionObserver의 첫 번째 인자로 진행되며, 계속 감시하면onIntersect() 함수가 여러 번 호출되기 때문에observer입니다.disconnect () 에서 감시를 잠시 중지한 적이 있습니다.onIntersect를 의존 배열로 하기 때문에, 업데이트할 때 (이 예에서 todos의 값이 바뀔 때) 이 함수는 다시 감시됩니다.두 번째 파라미터는 교차와 관련된 옵션이다.
ScrollObserver
  useEffect(() => {
  if (ref.current === null) return;
  const observer = new IntersectionObserver(
    (entries, observer) => {
      if (entries[0].intersectionRatio >= 1) {
        observer.disconnect();
        onIntersect();
      }
    },
    {
      threshold: 1,
    }
  );
  observer.observe(ref.current);
}, [onIntersect]);

isActiveObserver가 진짜일 때 (얻을 수 있는 todo가 남았을 때) 교차할 때 교차 처리를 하는 요소를 넣고 isActiveObserver가 가짜일 때null로 되돌아옵니다.
ScrollObserver.jsx
  return (
  <>
    {isActiveObserver ? (
      <div ref={ref} style={{ height: "50px", backgroundColor: "red" }}>
        <p>読み込み中...</p>
      </div>
    ) : null}
  </>
);

끝말


Intersection Observer API를 사용하여 무한 스크롤을 하는 것은 이번이 처음입니다. 좋지 않은 점이 있을 수 있지만 참고할 수 있다면 좋겠습니다!잘못된 점이나 더 좋은 점이 있으면 댓글로 남겨주세요()

좋은 웹페이지 즐겨찾기