カルキチブログ

ReactでIntersection Observer APIを使用したときの覚書

無限スクロールしたときにAPIを叩いて一覧を表示するみたいな実装をするときに、Intersection Observer APIを使って、監視している要素が可視状態になったときにデータのフェッチを行うみたいな実装をしたのですが、Intersection Observer APIの挙動がいまいちよくわかっていなかったので、少し深掘って調べてみました。

Intersection Observer APIとは?

Intersection Observer APIとは、ターゲット要素が祖先要素、または文書の最上位のビューポートと交差する変化を非同期的に監視する方法を提供するJavaScriptのAPIです。

mdnに書いてはありますが、いまいちピンときませんよね?

もっと噛み砕いて解釈すると、監視対象の要素を指定して、指定した要素が見えるようになったら処理を実行することができるJavaScriptのAPIです。

図で見るとだいぶイメージしやすくなると思ったので、図を作ってみました。

Intersection Observer APIの使い方

使用方法ですが、IntersectionObserverのインスタンスを生成して、生成したインスタンスのコールバック関数に監視対象の要素が見えた時の処理を記述して使用します。

// コールバック関数
const callback: IntersectionObserverCallback = (entries) => {
  // 監視対象の要素にはentry.targetでアクセスできる
  entries.forEach( (entry) => {
    // entry.isIntersectingで要素が領域内にあるかどうかをBooleanで判定できる
    if (entry.isIntersecting) {
      console.log('交差しています')
    }
  });
}

// オプションを指定する
const options: IntersectionObserverInit = {
  // ターゲットが見えるかどうかを確認するためのビューポートとして使用される要素。
  // 指定されなかった場合、は既定でブラウザーのビューポートが使用される。
  root: document.querySelector('#scrollArea'),
  // root要素の周りのmarginを指定できる
  rootMargin: '0px',
  // ターゲットがどのくらいの割合で見えている場合にオブザーバーのコールバックを実行するかを指定できる
  threshold: 1.0
}

const observer = new IntersectionObserver(callback, options)

Intersection Observer APIの使い道

以下のような使い道がありそうです。

  • ページをスクロールしたときに画像やコンテンツを表示する
  • スクロールによって目次の色を変更する
  • 無限スクロールの実装。(10件データを取得したとして、10件目が表示されたら11件目〜20件目のデータを取得して表示する)

従来の方法だと上記のような特定の位置に到達したときに処理を行うためには、scrollイベントを使用する必要がありましたが、scrollイベントだと、ブラウザの大きさを変更するなどでビューポートの高さが変更されてしまった場合に発火するのに必要なスクロール量が変わってしまうという欠点がありました。

この欠点を回避するために、window.resizeなどでスクロール量の再計算を行う必要がありました。

Intersection Observer APIは、スクロール量ではなく監視対象の要素が交差して見えたかどうかで処理を行うことができるので、ビューポートサイズの変更で交差する位置が変わっても、問題なく動作します。

さらに、window.scrollwindow.resizeはスクロールやリサイズのたびに処理が発火するので、パフォーマンスの面でもIntersection Observer APIの方が優っています。

既に全てのモダンブラウザで使用可能なので、特定の位置に到達したときに処理を行いたい場合は、Intersection Observer APIを使って実装するのが良さそうです。

この辺の解説は、ICS MEDIAの記事が分かりやすかったです。

Intersection Observer APIをReactで使ってみる

Reactで使うとこんな感じになるのかなと思います。

ref使ってDOMの参照を取得して、refで参照しているDOMが見えるようになったら処理を実行するみたいなイメージです。

まとめ

まとめていきます。

  • Intersection Observer APIとは、指定した要素が見えるようになったら処理を実行することができるJavaScriptのAPI。
  • 要素が見えるようになったら処理を行いたいときに使える。
  • window.scrollやwindow.resizeでも上記のような処理は書けるが、スクロールやリサイズのたびに処理が発火してしまい無駄が多いので、Intersection Observer APIを使って実装した方がいい。
  • Reactで書くときは、refでDOMの参照を保持して、参照しているDOMが見えたら 処理発火みたいな感じで書いていく。