LoginSignup
1
0

useEffect useLayoutEffect useInsertionEffect3つのEffectの挙動を見る

Posted at

はじめに

Reactで開発を行うにあたって外部システムとの同期をエフェクトを通じて行います。
エフェクトの利用はuseEffectが使われることが多く、次点でuseLayoutEffectが使われると考えています。そして、CSS in JSのライブラリ開発などではuseInsertionEffectが利用されます。

この記事ではそれらのエフェクトを利用する3つのhooksについて見ていきます。

useEffect

useEffectは以下のような型を持ちます。

declare const UNDEFINED_VOID_ONLY: unique symbol;
type Destructor = () => void | { [UNDEFINED_VOID_ONLY]: never };
type EffectCallback = () => void | Destructor;
type DependencyList = readonly unknown[];

function useEffect(effect: EffectCallback, deps?: DependencyList): void;

第1引数はエフェクトの内容を記述する関数です。この関数はコンポーネントがブラウザに初めて描画された後に実行されます。
第2引数はエフェクトの実行タイミングを管理する引数です。第2引数に値を渡さなかった場合はコンポーネントがブラウザに描画されるたびに再実行されます。第2引数に配列を渡した場合は各レンダリング時にその値が変化するたびにブラウザに描画された後に実行されます。空の配列を渡した場合は初回のブラウザへの描画後のみ実行されます。

第1引数の関数の返り値は型の上ではvoidを返すようになっていますが、クリーアップ関数と呼ばれる関数を返すようにも記述できます。この関数は新たなエフェクトが実行される直前に実行されます。実行されるのは新しいエフェクトの内容ではなく、実行されたエフェクトで記述された関数が実行されます(ローカル変数などは実行された時のものをそのまま使います)。

ブラウザへの描画が完了されるたびに実行される

useEffect(() => {
  console.log(1);
});

ブラウザへの初回描画が完了されるときに実行される

useEffect(() => {
  console.log(1);
}, []);

countの更新後にブラウザへの描画された後に実行される

useEffect(() => {
  console.log(1);
}, [count]);

クリーンアップ関数の順番

const Sample = () => {
  console.log('レンダリング時に実行される関数');
  useEffect(() => {
    console.log('ブラウザの描画後に実行される関数');
    () => {
      console.log('次のエフェクト実行時に実行される関数');
    };
  });
  return <></>;
};

useLayoutEffect

関数の形はuseEffectと同じですが、useLayoutEffectはエフェクト関数が描画される前に実行されます。

useInsertionEffect

useInsertionEffectuseLayoutEffectよりも早いタイミングでエフェクトを発火させます。早いタイミングでエフェクトが発火されるので、DOM情報をref経由で取得しようとしても、初回の実行では取得できていません。
そして、このhooksのエフェクト関数では状態の更新を行えないです。

比較

基本的にはuseEffectを利用することが推奨されているという前提であることに留意してください。
実行における順番は以下のようになっています。
スクリーンショット 2023-12-04 22.46.19.png
useInsertionEffectは基本的にCSS in JSからの動的スタイル注入されるために存在します。useInsertionEffectというuseLayoutEffectよりも早く実行されるhooksがあることでランタイム時の注入が間違ったタイミングで行われることよる遅延を防ぐことができます。間違ったタイミングとは他のuseLayoutEffectの処理と注入のタイミングが同じになることです。

そして、useEffectuseLayoutEffectは実行のタイミングが画面への描画前後という違いを活かして活用されます。基本的にはuseEffectを利用します。実行されるエフェクトが描画に関わるものであった場合にuseEffectを使うと画面に描画を行った後にエフェクトを実行して再度描画し直すような動きになるので、画面がチラつくことがあります。そのような場合はuseLayoutEffectを用いてチラつきを抑制します。

1
0
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
1
0