1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Intersection Observerを使ってスクロールでデータ取得できるようにする

Posted at

はじめに

就活の面接でIntersection Observerというワードが出たので、学習がてら個人開発に取り入れてみました。

Intersection Observerとは?

特定の要素が指定した領域に交差したかどうかを検知できるAPIです。これを使うことでもっとみるボタンなどを使わなくてもスクロールでデータの追加取得ができます。(xやyoutubeでも似たようなことしていると思います)
画面に表示されていない余計なデータを取得しなくていいですし、スクロールするだけでデータが取得されるのでパフォーマンスやユーザー体験の向上に役立ちそうです。

以下MDNを参考に作成したサンプルコードです。監視対象の要素(target)が画面に表示されたらcallbackが実行され、コンソールに"要素が画面に入りました!"と出力されます。オプションに関しては他にも色々あるので上記ドキュメントを見てみてください。

// 監視対象の要素を取得
const target = document.getElementById('target');

// スクロールで監視対象の要素が表示されると実行される関数
const callback = (entries) => {
   const entry = entries[0];
   // もし対象要素がビューポートと交差したら(画面に表示されたら)
   if (entry.isIntersecting) {
      console.log('要素が画面に入りました!');
   }
};

// オプションの指定
const options = {
   // 要素が完全に表示されたらcallbackを実行
   threshold: 1.0
};

// Intersection Observerコンストラクタを呼び出し、インスタンス生成
const observer = new IntersectionObserver(callback, options);

// 監視する対象要素を指定
observer.observe(target);

個人開発に取り入れてみた

もっとみるボタンを押して追加のデータ取得を行うのではなく、スクロールで追加取得できるようにしてみました。

Reactのサンプルコード
import { useRef, useCallback, useEffect } from "react";

export const LoadMore = ({ onLoadMore, loading, hasNextPage, keyword }) => {
  const sentinelRef = useRef(null);

  const handleObserver = useCallback(
    (entries) => {
      const target = entries[0];
      if (target.isIntersecting && !loading && hasNextPage && keyword) {
        onLoadMore();
      }
    },
    [loading, hasNextPage, onLoadMore, keyword]
  );

  useEffect(() => {
    const element = sentinelRef.current;
    if (!element) return;

    const observer = new IntersectionObserver(handleObserver, {
      rootMargin: "0px 0px -600px 0px",
      threshold: 1.0,
    });

    observer.observe(element);

    return () => observer.disconnect();
  }, [handleObserver]);

  return (
    <div className="text-center">
      {loading ? (
        <span className="loading loading-dots loading-xl mt-10"></span>
      ) : (
        <div ref={sentinelRef} className="h-10"></div>
      )}
    </div>
  );
};

test.gif

サンプルでは素のAPIを使って実装していますが、reactでお手軽にintersection observerを実装できるライブラリがあるみたいです。

おわりに

個人開発していたツールでは下部にフッターやサジェストワードを置いていたのと、特にデータ取得で困っていたわけではなかったので、もっとみるボタンで追加取得する形に戻しました(あと若干使いづらかった)。今後UIの構成など見直しつつ、必要に応じて活用していきたいです。

参考

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?