【入門編】 React Strict Modeにおける二重実行の理解 – React実践ガイド

【React】なぜuseEffectが2回動くの?Strict Modeの「二重実行」に隠された、開発者を守るための優しさ

Reactを学び始めて、最初に誰もが遭遇する「謎の現象」があります。

「よし!画面が開いたときに一回だけ実行したいから、`useEffect` を書こう」

そう思ってブラウザのコンソールを開いてみると……

画面が開いたよ!
画面が開いたよ!

「えっ!? なんで2回出力されてるの!? コードの書き方、間違えた……!?」

大丈夫ですよ、安心してくださいね。あなたの書いたコードは1ミリも間違っていません。バグでもありませんし、パソコンの調子がおかしいわけでもありません。

実はこれ、Reactがあなたのために意図的にやってくれている「安全のための予行練習」なのです。

今回は、Reactの「Strict Mode(厳格モード)」がなぜ `useEffect` を2回実行するのか、そしてそれがどうやって私たちの開発を助けてくれているのかを、身近な例えを交えて優しく紐解いていきましょう!

—

1. そもそも「Strict Mode(厳格モード)」ってなぁに?

Reactでアプリを作るとき、コードのどこかで `` というタグに囲まれているのを見たことはありませんか?

これは例えるなら、「超優秀な自動車の車検・安全点検モード」です。

  • 本番環境(ユーザーが見る実際の画面): 1回だけ実行される(普通に動く)
  • 開発環境(あなたがコードを書いている手元の画面): あえて2回実行して、危険がないかチェックする

そう、この2回実行される現象は「あなたがコードを書いている開発中だけ」に起きる特別なチェック機能なのです。本番で公開したときには勝手に2回動くことはありませんので、まずはホッと胸をなでおろしてくださいね。

—

2. なぜわざわざ「2回」実行するの?(イベント会場の例え話)

では、なぜReactはわざわざ2回も動かすのでしょうか?
ちょっと身近な「イベント会場の設営と撤去」で考えてみましょう。

あなたがイベントの設営担当者だとします。
「ステージの上に、大きな案内看板を1つ設置してください」と頼まれました。

  • 1回目の設置(マウント): 看板を置いた。
  • 撤去(クリーンアップ): 一度、看板を片付けた。
  • 2回目の設置(再マウント): もう一度、看板を置いた。

もしあなたが「片付け」を完璧にやっていれば、2回目に設置し直しても「看板は1枚だけ」正しく立っていますよね。

でも、もしあなたが片付けを忘れて、1回目の看板を置いたまま2回目の設置をしてしまったらどうでしょう?
ステージの上には「2枚の看板が重なってぐちゃぐちゃ」になってしまいます。

Reactはこれと同じテストを、ブラウザの中で一瞬のうちに行っているのです。

1. 副作用を実行する(看板を置く)
2. すぐに破棄してみる(看板を片付ける)
3. もう一度実行してみる(看板をもう一度置く)

「片付け(クリーンアップ関数)」を書き忘れていると、2回実行された瞬間に画面の表示がおかしくなったり、処理が重くなったりします。Reactはあえて2回動かすことで、「ねえ、片付けのコード忘れてない? 本番で事故が起きる前に気づいてね!」と、優しく教えてくれているのです。

—

3. 難しい言葉「冪等性(べきとうせい)」を世界一わかりやすく

Reactの公式ドキュメントなどを読んでいると、「冪等性(べきとうせい)」という難しそうな漢字が出てくることがあります。

難しく聞こえますが、意味はとってもシンプルです。

> 冪等性とは:
> 「1回やっても、100回やっても、得られる結果が同じであること」

身近なもので例えてみましょう。

  • 部屋の照明スイッチ:

「ON」のボタンは、1回押しても部屋が明るくなりますし、間違えて「ON」を10回連打しても部屋は「明るい状態」のままですよね。これが冪等性がある(安心な)状態です。

  • お会計のレジ:

「1,000円払う」ボタンを1回押したら1,000円引き落とされますが、もしシステムのエラーで2回押された判定になり、2,000円引き落とされたら大問題ですよね! これは冪等性がない(危険な)状態です。

Reactのコンポーネント(画面の部品)も、照明のスイッチのように「何回組み立て直されても、常に同じ正しい状態になってほしい」のです。

Strict Modeで `useEffect` を2回実行することは、「あなたの書いた処理は、2回連続で動いても安全な『冪等性』を持っていますか?」 というテストをしてくれているわけですね。

—

4. よくある失敗と「クリーンアップ関数」の魔法

では、実際にどんなコードだと危険で、どう直せばいいのかを見てみましょう!

よくあるのが「タイマー(setInterval)」や「イベントの監視(addEventListener)」を使うケースです。

✕ 良くない例:片付け(クリーンアップ)を忘れている

import { useEffect, useState } from ‘react’;

function BadCounter() {
const [count, setCount] = useState(0);

useEffect(() => {
// 1秒ごとにカウントを+1するタイマーを作る
setInterval(() => {
setCount((prev) => prev + 1);
}, 1000);

// びくびく… クリーンアップ(片付け)を書いていない!
}, []);

return

カウント: {count}

;
}

これをStrict Modeで動かすと、最初にタイマーが2つ作られてしまいます!
すると、1秒ごとにカウントが `1, 2` ではなく、`2, 4, 6, 8…` と倍速で増えていく恐ろしい現象が起きます。「あれ!? カウントが爆速で進むんだけど!?」というReact初心者あるあるのバグですね。

◯ 正しい例:しっかり片付け(クリーンアップ)を書いている

これを防ぐために、`useEffect` の中で「使い終わったら片付ける関数」を `return` してあげます。

import { useEffect, useState } from ‘react’;

function GoodCounter() {
const [count, setCount] = useState(0);

useEffect(() => {
// タイマーを開始し、そのIDをメモしておく
const timerId = setInterval(() => {
setCount((prev) => prev + 1);
}, 1000);

// ★ ここが超重要!「片付けの関数」を返す
// Reactがコンポーネントを破棄するとき(または2回実行の合間)にこれが呼ばれます
return () => {
clearInterval(timerId); // タイマーをきれいに解除!
};
}, []);

return

カウント: {count}

;
}

こう書かれていれば、Reactが開発環境で2回実行(作成→破棄→作成)しても、1回目のタイマーは綺麗に消去され、2回目のタイマーだけが正しく動き続けます。
カウントも正常に `1, 2, 3…` と増えていきますよ!

—

5. エディタに貼り付けて試せる!実践サンプルコード

ぜひお手元の環境(ViteやNext.jsなど)で、以下のコードをコピー&ペーストして動かしてみてください。
ブラウザのコンソール(F12キーで開く画面)を見ながら触ると、Reactの動きが手に取るようにわかりますよ!

import React, { useState, useEffect } from ‘react’;

export default function StrictModeDemo() {
const [logs, setLogs] = useState([]);

// ログを画面に追加するための補助関数
const addLog = (message) => {
setLogs((prev) => […prev, `${new Date().toLocaleTimeString()} – ${message}`]);
};

useEffect(() => {
// 1. 副作用の実行(設営)
console.log(‘🟢 [実行] useEffectが動き出しました!’);
addLog(‘🟢 [実行] useEffectが動き出しました!’);

// 2. クリーンアップ関数(撤去)
return () => {
console.log(‘🔴 [破棄] クリーンアップ関数が呼ばれました!’);
// ※setStateはアンマウント時に動かすと警告になることがあるため、コンソールログで確認します
};
}, []); // 空の依存配列=画面が開いたとき(マウント時)のみ

return (

Strict Mode 動作確認コンポーネント

ブラウザのデベロッパーツール(コンソール)を開いて確認してみましょう!

画面上のログ記録:

{logs.map((log, index) => (

{log}

))}

💡 ポイント:
コンソール画面を見ると、
🟢 [実行] ➔ 🔴 [破棄] ➔ 🟢 [実行]
の順番で、Reactがわざと「セットアップと片付け」をテストした形跡が見えるはずです!

);
}

—

まとめ:2回実行はReactからの「愛のメッセージ」

最初に `useEffect` が2回動くのを見たときは、「何か悪いことをしちゃったかな……」と不安になりますよね。

でも、仕組みを知ってみると、どうでしょう?

Reactは、あなたの作ったアプリが本番環境でユーザーの手によって動かされたとき、絶対に事故やバグが起きないように、陰でそっと予行練習をして守ってくれていたのです。

1. 2回実行されるのは開発環境(Strict Mode)だけ! 本番では1回だから安心してくださいね。
2. 2回動いて困る処理があったら、それは「片付け(クリーンアップ)」を忘れているサイン!
3. `return () => { … }` でしっかりお掃除をする習慣をつけましょう!

この仕組みが理解できたら、あなたはもうReactの初学者を脱出して、一歩先のアドバンスな開発者へ足を踏み入れていますよ。

バグを怖がらず、ぜひこの「2回実行」を味方につけて、快適なReact開発を楽しんでくださいね!応援しています!

コメント

タイトルとURLをコピーしました