はじめに
SPAではユーザーのスクロール操作に応じてUIを変えるニーズが多くあり、
私自身も自作しているReactアプリの中で「ある要素が今画面に見えているか」を検知しそれをトリガーにUIを切り替える方法を探していました。
今回、IntersectionObserver API を使用しFABの挙動をコントロールする手法をこの記事では紹介します。
IntersectionObserverとは
- ブラウザ上で要素が画面内に入っているかどうかを自動で検知できるAPI
- 見えている・見えていないをトリガーにしてUIを切り替える場面でよく使われる
ユースケース詳細
SearchFormが画面からスクロールで消えたら、代わりにFAB(フローティングボタン)を表示する設計です。
「ある要素の表示/非表示をトリガーにUIを切り替えたい」という場面で、IntersectionObserverを使うことができます。
実装手順
1. フォームを見張る
まず検索フォームに ref を渡せるようにしておきます。
React の Ref を使って書き換えます。
import type { RefObject } from 'react';
const searchFormRef = useRef(null);
2. トリガー対象となるフォーム(SearchForm)を監視対象として指定する
ref
特定の要素やコンポーネントを直接参照したいときにrefを使います。
DOMの位置や状態を検知したいときの橋渡しになる考え方です。
今回だとフォームが画面から消えた時がトリガーになるので、SearchFormを監視対象にします。
const searchFormRef = useRef(null);
<SearchForm
ref={searchFormRef} //このDOM要素を監視対象として指定する
/>
3. IntersectionObserverで表示状態を監視
次に、SearchFormが画面に見えているかどうかを自動で検知し、状態を更新します。
useEffect(() => {
// IntersectionObserverを新しく作成(entryで監視対象の状態を受け取る)
const observer = new IntersectionObserver(
([entry]) => {
// 監視対象が画面内に表示されていない場合(isIntersectingがfalse)、FABを表示
setShowFab(!entry.isIntersecting);
},
{ threshold: 0 } // 0%でも表示されていれば「見えている」と判定する
);
// 監視対象の要素が存在していれば、observerに登録
if (searchFormRef.current) {
observer.observe(searchFormRef.current);
}
// コンポーネントがアンマウント(画面から消える)された時、observerを解除(メモリリーク防止)
return () => observer.disconnect();
}, []);
4.FABコンポーネントを表示する
最後に、FABを表示するロジックを書きます。
<Fab isVisible={showFab} onClick={() => setIsModalOpen(true)} />
isVisible は showFab を渡します。
IntersectionObserverを使用することで、フォームの見える・見えないをトリガーにUIを切り替えることができました。
参考