【React 19.2新機能】useEffectEventをビギナー向けにやさしく解説
2025.10.9
この記事は約3分で読めます
目次

この記事の筆者:三好アキ
🟢 専門用語なしでプログラミングを教えるメソッドに定評があり、1200人以上のビギナーを、最新のフロントエンド開発入門に成功させる。
🟢『はじめてつくるReactアプリ with TypeScript』、『動かして学ぶ!Next.js/React開発入門(翔泳社/*韓国でも出版)』著者。
▼ Amazon著者ページはこちら
amazon.co.jp/stores/author/B099Z51QF2
React 19.2新機能【 useEffectEvent 】
10月1日にリリースされたReactバージョン19.2から、useEffectEventが使えるようになりました。
名前がuseEffectとよく似ています。
これはuseEffectEventが、useEffectの抱える問題点を解決するものとして作られたからです。
useEffectEventの機能を一言でいうと、「最新のprops/stateを参照できる」です。
ここから次の3つの具体的なメリットが出てきます。
• 依存配列の削減
• 不要なレンダリングの抑制
• ロジックの分離
本記事では、最初にuseEffectの問題点を確認し、次にuseEffectEventを使うメリットを実際にコードで紹介していきます。
Reactビギナー 〜 中級者向けの内容なので、事前知識は不要です。
なお、Reactバージョン19.2で導入された<Activity>については、下記記事をご覧ください。
useEffectの問題点(簡単な説明)
useEffectのコードの構造を見てみましょう。
useEffect(() => {
実行したい処理
}, []) // ←依存配列依存配列には、useEffect内で参照するstateやpropsを入れます。
なぜ入れる必要があるかというと、useEffect内部に置かれた処理において、最新のstateやpropsの値を利用できるようにするためです。
そのため、依存配列の中の値のどれか一つにでも変化があると、useEffectが実行されます。
しかし、依存配列内のstateやpropsが変化してもuseEffectの実行は不要、というケースもあります。
不要なuseEffectの動きを抑制する一番簡単な方法は、「依存配列からstateやpropsを取り除く」です。
確かにこれで不要なuseEffectの実行は回避できますが、その一方で、useEffect内に置かれた処理で最新のデータを参照できず、古いデータが使われ続けることになります。
とはいえ、このように言葉で説明していてもわかりづらいので、この点をコードで実際に確認してみましょう。
その中でuseEffectEventを使うメリットが見えてきます。
まずはReact + Viteのセットアップです。
準備(React + Vite)
ターミナルで次のコマンドを実行してください。
npm create vite@latest質問がいくつか出てくるので、次のように答えてください。
Project name:
│ react-useeffectevent
│
◇ Select a framework:
│ React
│
◇ Select a variant:
│ JavaScript
│
◇ Use rolldown-vite (Experimental)?:
│ No
│
◇ Install with npm and start now?
│ Noインストールが完了したら、VS Codeでフォルダを開きましょう。
現時点(2025年10月9日)では、デフォルトでReactバージョン19.1がインストールされているので、これを19.2にアップデートします。
package.jsonを開き、reactとreact-domのバージョンを次のように変更しましょう。
// package.json
...
"preview": "vite preview"
},
"dependencies": {
"react": "^19.2.0", // 変更
"react-dom": "^19.2.0" // 変更
},
"devDependencies": {
...変更を保存したら、インストールを実行します。
npm install次に不要なファイルとコードを消します。
srcフォルダ内のApp.cssは削除しましょう。
次にApp.jsxとindex.css内のコードをすべて消してください。
変更を保存したら、下記コマンドでReact + Viteを起動しましょう。
npm run devこれで準備は完了です。
React 19.2の新機能useEffectEventを見ていきましょう。
useEffectの問題を実際に確認
まずは従来からあるuseEffectの動きを見て、問題を確認していきます。
App.jsxに次のコードを書いてください。
「ボタンを押す度にcountstateが一つずつ増えていく」というだけのコードです。
保存したら、ブラウザで動きを確認してみてください。
// App.jsx
import { useState } from "react"
const App = () => {
const [count, setCount] = useState(0)
return (
<div>
<p>カウント数: {count}</p>
<button onClick={() => setCount(count + 1)}>+ボタン</button>
</div>
)
}
export default App次はここにuseEffectを書き足しましょう。
下記コードを追加してください。
// App.jsx
import { useEffect, useState } from "react" // 追加
const App = () => {
const [count, setCount] = useState(0)
// ▼追加
useEffect(() => {
console.log("useEffectが実行されました")
const timer = setTimeout(() => {
alert(`現在のカウント数は ${count} です`)
}, 5000)
return () => clearTimeout(timer)
}, [])
// ▲追加
return (
<div>
<p>カウント数: {count}</p>
<button onClick={() => setCount(count + 1)}>+ボタン</button>
</div>
)
}
export default Appいま書いたコードを解説します。
useEffectの最後を見てください。
カラの依存配列([])があるので、このuseEffectは初回レンダリング時に一回だけ実行されるとわかります。
そこで行われる処理は次の2つです。
• console.log() ▶︎ useEffectの動きを確認するため
• alert() ▶︎ カウント数を表示する
なおalert()は、setTimeout()で挟まれています。
setTimeout()の働きは遅延を引き起こすことです。
そのため、初回レンダリングから5秒後にalert()が実行されることになります。
そして最後のclearTimeout()はクリーンアップ(後片付け)のためです(これがないとsetTimeout()が意図通りに動かないことがあります)。
ブラウザで動きを確認してみましょう。
保存をしたらブラウザを開いてください。
5秒経つとalert()が表示されます。
次は、リロード(command + R)をしてください。
そして「+ボタン」を数回押しましょう。
5秒経つと再びalert()が表示されます。
しかしここで、少しおかしなことに気がつきます。
カウント数は上がっているのに、alert()上の数は0のままなのです。
理由を説明します。
これは依存配列がカラで、useEffectが初回レンダリング時にしか動いていないためです。
つまり、ボタンが押されて数が増えたcountstateではなく、初回レンダリング時点の0のcountstate、つまり「古いstate」が参照されているのです。
この解決法は、「countstateが増える度にuseEffectを実行する」となります。
そうすれば最新のcountstateを参照できるでしょう。
countを依存配列に加えてください。
// App.jsx
import { useEffect, useState } from "react"
const App = () => {
const [count, setCount] = useState(0)
useEffect(() => {
console.log("useEffectが実行されました")
const timer = setTimeout(() => {
alert(`現在のカウント数は ${count} です`)
}, 5000)
return () => clearTimeout(timer)
}, [count]) // 追加
return (
<div>
<p>カウント数: {count}</p>
<button onClick={() => setCount(count + 1)}>+ボタン</button>
</div>
)
}
export default App変更を保存してブラウザを開いたら、「+ボタン」を数回押してください。
最後の押下から5秒経つとalert()が表示されます。
今回の数はカウント数と同じです。
ここで注目して欲しいのは、alert()の実行が「最後のボタン押下から5秒後」という点です。
これはuseEffectが、ボタン押下の度に実行されていることに由来します。
確認してみましょう。
開発者ツールから「console」を開いてください。
リロード(command + R)をしたら、ボタンを数回押しましょう。
すると次のように表示が出て、ボタン押下の度にuseEffectが動いているのがわかります。
しかし、このように毎回useEffectが実行されることはブラウザの負荷を高めます。
さらにuseEffectが毎回実行されることによって、alert()の表示も「最後のボタン押下から5秒後」となってしまっています。
依存配列にcountを加えた理由を思い出してください。
最新のcountstateを参照するためです。
countstateの最新状態を取得できるのであれば、useEffectは毎回実行されなくていいのです。
ここで使うのが、本記事のメインテーマuseEffectEventになります。
useEffectEventで問題を解決する
まずはalert()の部分をuseEffect外部に切り出しましょう。
App.jsxのコードを次のように変更してください。
alert()をshowAlertというfunctionの中に移しただけなので、動きは先ほどと同じです。
// App.jsx
import { useEffect, useState } from "react"
const App = () => {
const [count, setCount] = useState(0)
const showAlert = () => {
alert(`現在のカウント数は ${count} です`)
}
useEffect(() => {
console.log("useEffectが実行されました")
const timer = setTimeout(() => {
showAlert()
}, 5000)
return () => clearTimeout(timer)
}, [count])
return (
<div>
<p>カウント数: {count}</p>
<button onClick={() => setCount(count + 1)}>+ボタン</button>
</div>
)
}
export default App保存をしたらブラウザを見てください。
先ほども確認した次の2つのことがわかります。
• alert()の実行は最後のボタン押下から5秒後
• ボタン押下の度にuseEffectが実行
ここでuseEffectEventを使いましょう。
次のように加えてください。
// App.jsx
import { useEffect, useState, useEffectEvent } from "react" // 追加
const App = () => {
const [count, setCount] = useState(0)
const showAlert = useEffectEvent(() => { // 追加
alert(`現在のカウント数は ${count} です`)
}) // 追加
useEffect(() => {
console.log("useEffectが実行されました")
const timer = setTimeout(() => {
showAlert()
}, 5000)
return () => clearTimeout(timer)
}, []) // 削除
return (
<div>
<p>カウント数: {count}</p>
<button onClick={() => setCount(count + 1)}>+ボタン</button>
</div>
)
}
export default App依存配列からcountstateを消すのを忘れないようにしましょう。
保存したら、ブラウザで動きを確認してください。
注目して欲しいのは3点で、alert()の実行タイミング、alert()上のカウント数、そして「console」です。
useEffectは初回レンダリング時にしか動いていないにもかかわらず、正しいカウント数がalert()に表示されているのがわかります。
さらにalert()の実行タイミングも、「最後のボタン押下から5秒後」ではなく「初回レンダリングから5秒後」になっています。
useEffectEventを使うことで、useEffectを毎回実行させることなく、最新のcountstateを参照できるようになったのです。
さらに、ロジック部分を切り出したので、コードの見通しがよくなったこともボーナス的なメリットとして挙げられます。
useEffectEventを使うことで、依存配列の管理が楽になり、useEffectの不要な再実行を抑えることができます。
さらに、処理の具体的な中身(WHAT to do)と、その処理の実行タイミング(WHEN to do)を分離できます。
Reactバージョン19.2で追加されたもう一つの目玉機能<Activity>もこちらの記事で紹介しているので、確認してください。
▼【無料フロントエンド・ガイド】は下記ページで受け取れます。

🟩 フロントエンド開発者入門ガイド【無料配布中】
最初にこれが知りたかった!
フロントエンド初心者が必ず押さえておきたい ― 『挫折しない勉強法』とその具体的ステップ、無料配布中。
(*名前不要・メールアドレスだけで受け取り可能です)


