4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

react-visibility-sensorを使って、ブラウザの表示領域内に入っている時だけ動くコンポーネントを作る

Posted at

react-visibility-sensorとは

react-visibility-sensor は、そのコンポーネントがブラウザの表示領域に入っているかをチェックしてくれるライブラリです。

このライブラリを使うことで、ブラウザ上で見えている場合にだけ、動作するコンポーネントを作ることができます。

サンプル: https://github.com/geekduck/visibility-sensor-sample

デモ1

コンポーネントが表示領域内(白色の領域)に存在している場合にだけ、

タイマーで現在時刻を更新するコンポーネントを作ってみました。

600-30fpx.gif

サンプルコード

コンポーネントが表示領域に出たり入ったりするたびに、VisibilitySensoronChangeに渡した関数が実行されます。

const CurrentTimer = () => {
    const [currentTime, setCurrentTime] = useState(new Date());
    const [timerId, setTimerId] = useState(0);

    useEffect(() => {
        return () => clearInterval(timerId); // タイマーの後始末
    }, [timerId]);

    const onChange = (isVisible) => {
        if (isVisible) {
            // このコンポーネントが表示されている場合、タイマーで現在時刻を更新する。
            setTimerId(setInterval(() => {
                setCurrentTime(new Date());
            }, 10));
        } else {
            // このコンポーネントが表示されていない場合、タイマーを削除して現在時刻を更新しない。
            clearInterval(timerId);
            setTimerId(undefined);
        }
    };

    return (
        <VisibilitySensor
            onChange={onChange} // コンポーネントの表示状態が変わるたびに実行される
            partialVisibility={true} // 表示領域にちょっとでも入っていたらisVisible=trueと判定させる。
            offset={{top: 100, bottom: 100}} // 見た目でわかりやすいように、上下100pxの範囲は表示領域外にする。
        >
            <div className="CurrentTimer">{dayjs(currentTime).format('YYYY/MM/DD HH:mm:ss.SSS')}</div>
        </VisibilitySensor>
    );
};

デモ2

VisibilitySensorコンポーネントの子要素として、関数を渡すこともできます。

return (
    <VisibilitySensor
        onChange={onChange} // コンポーネントの表示状態が変わるたびに実行される
        partialVisibility={true} // 表示領域にちょっとでも入っていたらisVisible=trueと判定させる。
        offset={{top: 100, bottom: 100}} // 見た目でわかりやすいように、上下100pxの範囲は表示領域外にする。
    >
        {
            ({isVisible}) => isVisible
                ? <div className="CurrentTimer">{dayjs(currentTime).format('YYYY/MM/DD HH:mm:ss.SSS')}</div>
                : <div className="CurrentTimer"/> // 表示されていない場合は、子要素を表示しない。
        }
    </VisibilitySensor>
);

この場合、関数の引数としてisVisibleが取得できるので、

表示されていない場合は空のdiv要素を表示して、renderの負荷を下げるコードが書けます。

600-30fps-2.gif

類似のライブラリ

表示領域外のコンポーネントをrenderしないライブラリとして有名なものは、react-windowや、react-virtualizedがあります。

大量のコンポーネントをリスト形式で表示する際は、これらのライブラリを使う方が適切です。

参考

4
4
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
4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?