useInsertionEffect 完全入門【React】CSS-in-JSライブラリ向けの特殊フック

ReactのuseInsertionEffectとは何か、CSS-in-JSライブラリでのスタイル挿入における役割を解説。一般的なアプリ開発での使用場面と、useEffectやuseLayoutEffectとの実行タイミングの違いも紹介します。

#react#hooks#useinsertioneffect#javascript#frontend

React のフックの中でも、useInsertionEffect は一般的なアプリ開発ではほとんど使うことのない特殊なフックです。

このフックは主に CSS-in-JS ライブラリの開発者を対象としており、スタイルを DOM に挿入するタイミングを最適化するために設計されています。「なんのためにあるのか」を理解することで、React のレンダリング仕組みへの理解も深まります。

この記事でわかること:

  • useInsertionEffect が生まれた背景
  • useEffectuseLayoutEffect との実行タイミングの違い
  • CSS-in-JS ライブラリでの使用例
  • 一般アプリ開発者が知っておくべきポイント

useInsertionEffect とは?

useInsertionEffect は、レイアウトエフェクトが発火する前に DOM にスタイルを挿入するためのフックです。

useInsertionEffect(setup関数, 依存配列);

useEffectuseLayoutEffect と同じ API ですが、実行タイミングが異なります。

3つのエフェクトの実行タイミング

① React が DOM を更新する
      ↓
② useInsertionEffect が実行される  ← 最初に実行(スタイル挿入)
      ↓
③ useLayoutEffect が実行される     ← レイアウト測定
      ↓
④ ブラウザが画面を描画する
      ↓
⑤ useEffect が実行される           ← 描画後

useInsertionEffect が最も早いタイミングで実行されることで、他のエフェクトが実行される時点ではスタイルがすでに適用された状態になります。

なぜ必要なのか?

CSS-in-JS ライブラリ(emotion、styled-components など)は、コンポーネントのレンダリング時にスタイルを動的に生成して DOM に挿入します。

もし useLayoutEffect の中でスタイルを挿入すると、以下の問題が起きます:

① DOM 更新
② useLayoutEffect 実行中にスタイル挿入
   → ブラウザが強制的にスタイルを再計算する(パフォーマンス低下)
③ ブラウザ描画

useInsertionEffect を使うことで、レイアウト計算が始まる前にスタイルを挿入でき、ブラウザの強制的なスタイル再計算を避けられます

CSS-in-JS ライブラリでの使用例

// CSS-in-JS ライブラリの内部実装イメージ
function useCSS(rule) {
  useInsertionEffect(() => {
    // レイアウトエフェクトより前にスタイルを DOM に挿入する
    if (!isInserted.has(rule)) {
      isInserted.add(rule);
      document.head.appendChild(getStyleForRule(rule));
    }
  });
 
  return rule;
}
 
// コンポーネントからの利用
function Button() {
  const className = useCSS("button { color: blue; }");
  return <button className={className}>クリック</button>;
}

重要な制約

useInsertionEffect には通常のエフェクトにはない制約があります:

制約説明
state の更新不可エフェクト内から state を更新できない
ref 未アタッチ実行時点では ref はまだ DOM にアタッチされていない
クライアントのみサーバーサイドレンダリング中は実行されない
// ❌ NG:useInsertionEffect 内で state を更新してはいけない
useInsertionEffect(() => {
  setState(something); // エラーになる
});

一般的なアプリ開発者へのアドバイス

useInsertionEffectライブラリ開発者向けのフックです。アプリ開発では通常使いません。

用途使うフック
データ取得・イベントリスナーuseEffect
DOM 測定・レイアウト調整useLayoutEffect
CSS-in-JS スタイル挿入(ライブラリ内部)useInsertionEffect

styled-components や emotion などの CSS-in-JS ライブラリを使う側の立場では、このフックの存在を意識する必要はありません。ライブラリが内部で適切に処理してくれます。

まとめ

  • useInsertionEffect は CSS-in-JS ライブラリ開発者向けの特殊なフック
  • useLayoutEffect よりも早いタイミングでスタイルを DOM に挿入できる
  • ブラウザの強制スタイル再計算を防ぎ、パフォーマンスを向上させる
  • state の更新や ref へのアクセスはできない
  • 一般的なアプリ開発では使わなくてよい

関連記事