🖥️
【React】特定の要素が画面内 / 画面より上 / 画面より下のどこにあるかを調べるカスタムフック
Reactにおいて、特定の要素が現在
- 画面内(ビューポート内)に存在する
- 画面より上に存在する
- 画面より下に存在する
のどれに該当するかをチェックするカスタムフックを作った(ものの使わなかった)ので供養しておきます。パフォーマンスのためにIntersection Observerを使っています。
カスタムフックを作成
useOnScreen.tsx
import React, { useState, useEffect } from 'react';
type TargetViewPosition = undefined | 'ABOVE_VIEWPORT' | 'BELOW_VIEWPORT' | 'VISIBLE';
export function useOnScreen(targetRef: React.RefObject<HTMLElement>) {
const [targetViewPosition, setTargetViewPosition] = useState<
TargetViewPosition
>(undefined);
const observer = new IntersectionObserver(
([entry]) => {
if (entry.isIntersecting) {
setTargetViewPosition('VISIBLE'); // 画面内に表示中
return;
}
if (entry.boundingClientRect.top > 0) {
setTargetViewPosition('BELOW_VIEWPORT'); // 画面より下に表示中
} else {
setTargetViewPosition('ABOVE_VIEWPORT'); // 画面より上に表示中
}
},
{
root: null,
threshold: 0,
}
);
useEffect(() => {
// マウント時にobserverを登録
if (targetRef.current) observer.observe(targetRef.current);
// アンマウント時にobserverを解除
return () => {
observer.disconnect();
};
}, []);
return targetViewPosition;
}
使い方
↓ カスタムフックの引数には画面上の位置を知りたい要素のrefを渡します。
SomeComponent.tsx
import { useOnScreen } from "./useOnScreen.tsx"
export const SomeComponent: React.VFC = () => {
const targetViewPosition = useOnScreen();
return (
<>
{targetViewPosition === 'VISIBLE' && <p>画面内に表示されています</p>}
{targetViewPosition === 'ABOVE_VIEWPORT' && <p>画面より上に表示されています</p>}
{targetViewPosition === 'BELOW_VIEWPORT' && <p>画面より下に表示されています</p>}
<div ref={targetRef}>位置をチェックする対象の要素</div>
</>
)
}
あまり使いどころはないかもしれませんが。
Discussion