【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
と名前がよく似ています。
これはuseEffect
の問題点を解消する機能がuseEffectEvent
にはあるからです。
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
に次のコードを書いてください。
「ボタンを押す度にcount
stateが一つずつ増えていく」というだけのコードです。
保存したら、ブラウザで動きを確認してみてください。
// 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
が初回レンダリング時にしか動いていないためです。
そのため、ボタンが押されて数が増えたcount
stateではなく、初回レンダリング時点の0
のcount
state、つまり「古いstate
」が参照されているのです。
この解決法は、「count
stateが押される度にuseEffect
を実行する」となります。
そうすれば最新のcount
stateを参照できるでしょう。
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
を加えた理由を思い出してください。
最新のcount
stateを参照するためです。
count
stateの最新状態を取得できるのであれば、useEffect
は毎回実行されなくていいのです。
ここで使うのがuseEffectEvent
です。
useEffectEventで問題を解決する
まずはalert()
の部分をuseEffect
外部に切り出しましょう。
App.jsx
のコードを次のように変更してください。
alert()
の位置を変えただけなので、動きは先ほどと同じです。
// 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
依存配列からcount
stateを消すのを忘れないようにしましょう。
保存したら、ブラウザで動きを確認してください。
注目して欲しいのは3点で、alert()
の実行タイミング、alert()
上のカウント数、そして「console」です。
useEffect
は初回レンダリング時にしか動いていないにもかかわらず、正しいカウント数がalert()
に表示されているのがわかります。
さらにalert()
の実行タイミングも、「最後のボタン押下から5秒後」ではなく「初回レンダリングから5秒後」になっています。
useEffectEvent
を使うことで、useEffect
を毎回実行させることなく、最新のcount
stateを参照できるようになったのです。
さらに、ロジック部分を切り出したので、コードの見通しがよくなったこともボーナス的なメリットとして挙げられます。
useEffectEvent
を使うことで、依存配列の管理が楽になり、useEffect
の不要な再実行を抑えることができます。
さらに、処理の具体的な中身(What to do)と、その処理の実行タイミング(When to do)を分離できます。
Reactバージョン19.2で追加されたもう一つの目玉機能<Activity>
もこちらの記事で紹介しているので、確認してください。
▼【無料フロントエンド・ガイド】は下記ページで受け取れます。

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