ReactのuseLayoutEffectとuseEffectの違いを徹底解説!初心者でもわかるライフサイクル活用法
生徒
「ReactでuseEffectとuseLayoutEffectって何が違うんですか?」
先生
「どちらも副作用を扱うフックですが、タイミングが違います。簡単に言うと、画面が描画される前か後かの違いです。」
生徒
「画面の描画前と後って、どういう場合に使い分けるんですか?」
先生
「例えばDOMのサイズを測ってレイアウトを調整する場合はuseLayoutEffect、データ取得やログ出力のように画面描画に影響しない処理はuseEffectを使います。」
1. useEffectとは?
useEffectは、Reactで副作用(サイドエフェクト)を扱うための基本的なフックです。 副作用とは、画面の描画そのものとは直接関係しない処理のことで、 代表的な例としてはデータの取得、ログの出力、タイマーの設定、イベントの登録などがあります。 Reactでは、こうした処理をコンポーネントの外ではなく、 useEffectの中にまとめて書くのが一般的です。
useEffectの大きな特徴は、画面が描画されたあとに実行されるという点です。 そのため、画面表示を邪魔しにくく、パフォーマンスへの影響も比較的少なくなります。 初回表示のときだけ処理を行ったり、特定の値が変わったときだけ処理を行ったりと、 条件を指定して実行できるのも使いやすいポイントです。
import React, { useState, useEffect } from "react";
function Example() {
const [count, setCount] = useState(0);
useEffect(() => {
console.log("useEffect: カウントが変わりました", count);
}, [count]);
return (
<div>
<p>カウント: {count}</p>
<button onClick={() => setCount(count + 1)}>増やす</button>
</div>
);
}
export default Example;
この例では、countの値が変わるたびにuseEffectの中の処理が実行されます。
画面上の表示が先に更新され、そのあとでログが出力されるため、
ユーザーの操作感を損なうことがありません。
初心者の方は、まず「useEffectは画面表示のあとに動く処理を書く場所」
と覚えておくと理解しやすくなります。
2. useLayoutEffectとは?
useLayoutEffectもuseEffectと同じく、副作用を扱うためのReactフックです。 ただし大きな違いとして、DOMの変更が画面に描画される直前に処理が実行されます。 そのため、画面が表示されたあとではなく、 表示される「直前の状態」でDOMを操作できる点が特徴です。
この性質を活かして、要素のサイズや位置を正確に取得したり、 描画前にスタイルを調整したりする処理に向いています。 一方で、レンダリングを一時的に止めて処理が行われるため、 内容が重いと画面表示が遅くなる原因にもなります。 初心者の方は「見た目に直接関係する処理だけに使う」と覚えておくと安心です。
import React, { useState, useLayoutEffect, useRef } from "react";
function LayoutExample() {
const boxRef = useRef();
const [width, setWidth] = useState(0);
useLayoutEffect(() => {
setWidth(boxRef.current.offsetWidth);
console.log("useLayoutEffect: ボックスの幅", boxRef.current.offsetWidth);
}, []);
return (
<div>
<div ref={boxRef} style={{ width: "50%" }}>ボックス</div>
<p>幅: {width}px</p>
</div>
);
}
export default LayoutExample;
この例では、ボックスが画面に表示される前に幅を取得しています。 そのため、表示された瞬間から正しいサイズが反映され、 レイアウトのズレやチラつきが起きにくくなります。 「表示前に整えておきたい処理があるかどうか」が、 useLayoutEffectを選ぶ一つの判断基準になります。
3. useEffectとuseLayoutEffectの使い分け
- 画面描画に関係する処理: useLayoutEffect
- 画面描画に影響しない処理: useEffect
useEffectとuseLayoutEffectは見た目が似ているため迷いやすいですが、 判断のポイントはとてもシンプルです。 「その処理は、画面に表示されるタイミングに影響するかどうか」を考えてみましょう。 表示結果が変わらない処理であれば、基本的にuseEffectで問題ありません。
例えば、APIからデータを取得して一覧を表示する場合や、 ボタン操作のログを記録するような処理は、 画面が表示されたあとに動いても違和感がありません。 一方で、要素のサイズを元に配置を決める処理や、 表示ズレを防ぐための微調整が必要な場合は、 描画前に処理できるuseLayoutEffectが適しています。
初心者の方は、まずはuseEffectを選び、 「表示が一瞬ずれる」「チラつく」と感じたときに、 useLayoutEffectを検討する流れがおすすめです。 この順番を意識するだけで、無理なく正しい使い分けができるようになります。
4. useEffectとuseLayoutEffectを理解するための重要ポイント
- useEffectはレンダリング後に実行される副作用用フック
- useLayoutEffectはレンダリング前に実行され、DOM操作やレイアウト調整に向いている
- パフォーマンスと描画タイミングを考えて使い分けることが大切
Reactアプリを作るときには、この違いを理解することで、描画のちらつきや不具合を防ぎつつ効率的に副作用を管理できます。
5. useEffectが向いている具体的なケース
useEffectは、画面の見た目そのものには直接影響しない処理を扱う場面で力を発揮します。 代表的なのが、APIからのデータ取得やログの出力、イベントリスナーの登録などです。 これらの処理は、画面が一度描画されたあとに実行されても問題がないため、 useEffectを使うことで表示パフォーマンスを保ちやすくなります。
特に初心者の方は、「まずはuseEffectを基本として使う」と考えると分かりやすいです。 Reactでは多くの副作用がuseEffectだけで十分に対応できるため、 無理にuseLayoutEffectを使わなくても、ほとんどのケースは問題なく実装できます。 画面表示と処理を切り分けて考える意識を持つことが大切です。
6. useLayoutEffectを使うときの注意点
useLayoutEffectは、DOMが画面に反映される直前に処理が実行されるため、 使い方を誤るとパフォーマンスに影響を与えることがあります。 処理が重い場合、画面の描画そのものが遅れ、 ユーザーから見ると操作がもたついているように感じられることもあります。
そのため、useLayoutEffectでは必要最小限の処理だけを書くことが重要です。 DOMのサイズ取得やスクロール位置の補正など、 「どうしても描画前でなければならない処理」に限定して使うことで、 Reactアプリ全体の動作を安定させることができます。
7. 初心者が混乱しやすいポイント
useEffectとuseLayoutEffectの違いで、初心者が特に混乱しやすいのは、 「どちらも同じように見える」という点です。 実際、コードの書き方はほぼ同じなので、 実行タイミングの違いを意識しないと使い分けが難しく感じられます。
迷ったときは、「画面に一瞬でも影響が出るかどうか」を基準に考えてみてください。 影響が出ない処理ならuseEffect、表示のズレやチラつきを防ぎたいならuseLayoutEffect、 という考え方を習慣にすると判断しやすくなります。 この基準を身につけることで、Reactのライフサイクル理解が自然と深まっていきます。
まとめ
useEffectとuseLayoutEffectの違いを振り返る
この記事では、Reactでよく使われるフックであるuseEffectとuseLayoutEffectについて、 それぞれの役割や実行されるタイミングの違いを丁寧に確認してきました。 どちらも副作用を扱うための仕組みですが、最大の違いは「いつ処理が実行されるか」という点です。 useEffectは画面が描画されたあとに実行されるため、画面表示に直接影響しない処理に向いています。 一方でuseLayoutEffectは、画面に反映される直前に実行されるため、 DOMのサイズ測定やレイアウト調整など、見た目に関わる処理に適しています。
初心者の方にとっては、最初はこの違いが少し分かりにくく感じられるかもしれません。 しかし「画面が表示されてから動いてもよい処理か」 「表示される前に必ず終わっていてほしい処理か」という視点で考えると、 自然と使い分けができるようになります。 フックの名前を覚えることよりも、画面との関係を意識することが理解への近道です。
実務で役立つ考え方
実際の開発現場では、画面のちらつきや一瞬のズレがユーザー体験に大きく影響することがあります。 例えば、要素の幅を取得して配置を調整する処理がuseEffectで書かれていると、 初回表示時にレイアウトが一瞬崩れて見えることがあります。 こうした場合にuseLayoutEffectへ切り替えるだけで、表示が安定することも少なくありません。 逆に、通信処理やログ出力のように表示と無関係な処理をuseLayoutEffectに書いてしまうと、 画面の描画が遅くなり、操作感が悪くなる原因になります。
そのため、「見た目に関係するかどうか」「処理が重くないか」という二つの観点を持つことが重要です。 すべてをuseLayoutEffectで書くのではなく、 必要な場面にだけ使うことで、パフォーマンスと見た目のバランスを保つことができます。 この判断ができるようになると、Reactのライフサイクル理解が一段深まります。
シンプルなサンプルで最終確認
import React, { useEffect, useLayoutEffect, useRef, useState } from "react";
function SummaryCheck() {
const boxRef = useRef(null);
const [width, setWidth] = useState(0);
const [count, setCount] = useState(0);
useLayoutEffect(() => {
if (boxRef.current) {
setWidth(boxRef.current.offsetWidth);
}
}, []);
useEffect(() => {
console.log("カウントが変わりました", count);
}, [count]);
return (
<div>
<div ref={boxRef} style={{ width: "50%" }}>ボックス</div>
<p>幅: {width}px</p>
<p>カウント: {count}</p>
<button onClick={() => setCount(count + 1)}>増やす</button>
</div>
);
}
export default SummaryCheck;
このように、役割ごとにフックを使い分けることで、 処理の意図が分かりやすくなり、後からコードを見直したときも理解しやすくなります。 初心者のうちは小さなサンプルで挙動を確認しながら、 「なぜこちらを使うのか」を言葉で説明できるようになることが大切です。
生徒
「useEffectとuseLayoutEffectの違いが、だいぶ整理できました。 今までは何となく使っていましたが、 画面に出る前か後かで考えると判断しやすいですね。」
先生
「それが一番大事なポイントです。 表示が崩れたときは、まず実行タイミングを疑うクセをつけると、 原因にたどり着きやすくなります。」
生徒
「これからは、通信やログはuseEffect、 サイズや位置の調整はuseLayoutEffect、という意識で書いてみます。」
先生
「その考え方で問題ありません。 少しずつ経験を積めば、Reactのライフサイクルが自然と身についていきますよ。」