【React】useEffectによく似たhook useLayoutEffect

こちらのReactハンズオンラーニングより学ばせていただいたこと内容をまとめています。

書籍の説明

書籍名: Reactハンズオンラーニング 第2版 ―Webアプリケーション開発のベストプラクティス
著者: Alex Banks 著
出版社: オライリージャパン 発行
発売日: 2021/8/6

useEffectに、名前も機能もよく似たuseLayoutEffectというhookがあり、それについてまとめました。

useEffectとuseLayoutEffectの違い

useLayoutEffectは、コンポーネントの描画サイクルの特定の箇所で呼び出されるhookです。

特定ってなんだよ?

useEffectとuseLayoutEffectを同コンポーネントに記述することにより違いを比較します。

import { useEffect, useLayoutEffect } from "react";

export const UseLayoutEffect = () => {
  useEffect(() => console.log("useEffect"));
  useLayoutEffect(() => console.log("useLayoutEffect"));
  return <div>ready</div>;
};

import { UseLayoutEffect } from "./components/UseLayoutEffect";

function App() {
  return (
    <>
      <UseLayoutEffect />
    </>
  );
}

export default App;

こちらのコンソールの出力結果は以下のようになります。

useLayoutEffect
useEffect

useLayoutEffectの方が先に出力されます。

これはなぜでしょう?

useLayoutEffectで設定された副作用が実行されるタイミングは、コンポーネントの描画関数が呼ばれるよりも後。これはuseEffectと同じです。

この後が異なります。

useLayoutEffectは、描画結果が画像に表示されるよりも前。

useEffectは画像に表示された後。

つまり、useEffectは、描画が画像に反映される前に処理を実行したい場合に使います。

実行順を整理するとこうなります。

useEffect

コンポーネントの描画関数(returnの後)呼び出し → 画面表示 → useEffectの関数実行

useLayoutEffect

コンポーネントの描画関数(returnの後)呼び出し → useEffectLayoutの関数実行 → 画面表示

実用例

実用例として、マウスの座標を追跡するカスタムフックを作ってみます。

import { useState, useLayoutEffect } from "react";

function useMousePosition() {
  const [x, setX] = useState(0);
  const [y, setY] = useState(0);

  const setPosition = ({ x, y }) => {
    setX(x);
    setY(y);
  };

  useLayoutEffect(() => {
    // マウスを動かしたときにsetPositionが発動する
    window.addEventListener("mousemove", setPosition);
    // setPositionを解除
    return () => window.removeEventListener("mousemove", setPosition);
  }, []);

  return [x, y];
}

この場合、順番としては、

  1. [x, y]が呼び出される
  2. useLayoutEffect内の関数が呼び出される
  3. 2での処理結果が、画面に反映される

useEffectの場合だと、画面に反映された後にuseEffectの処理結果が返ってくるため表示されない。

useLayoutEffectの使い所を習得することができました。

以上、読んでいただきありがとうございました。

コメント