[React 18] useEffect が2回実行されてしまう問題の対処法

3 min read

React 18 から、厳密モードが有効になっている開発モードでのみ useEffect が 2 回実行されるようになった。

確認した環境

現象を確認したのは以下の環境。

  • next: v12.2.2
  • react: v18.2.0
  • react-dom: v18.2.0

解決方法

以下のいずれかで対応が可能。

StrictModeコンポーネントを削除する

厳密モードでなくすることで防ぐ。

import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import App from "./App";

const rootElement = document.getElementById("root");
const root = createRoot(rootElement);

root.render(
  // <StrictMode>
  <App />
  // </StrictMode>
);

クリーンアップ関数を定義する

クリーンアップ関数を定義して複数回実行されても問題ないようにする。

const [results, setResults] = useState([]);
const [page, setPage] = useState(1);

useEffect(() => {
  let ignore = false;

  fetchResults(query, page).then((json) => {
    if (!ignore) {
      setResults(json);
    }
  });

  return () => {
    ignore = true;
  };
}, [query, page]);

useRefを利用する

const refFirstRef = useRef(true);

useEffect(() => {
  if (process.env.NODE_ENV === "development") {
    if (refFirstRef.current) {
      refFirstRef.current = false;
      return;
    }
  }

  something();
}, []);

プロダクションビルド時に実行されなくなってしまうため、process.env.NODE_ENV === 'development'の判定を入れて開発モードのみの処理にしておく。

参考

Next Read

[初学者向け] Next.js で開発を始める方法

想定読者 / Next.js とは / なぜ、Next.js を使うのか / セットアップ / ファイルベースルーティング / 事前レンダリング(プリレンダリング)とは / 参考

[Next.js] Emotion SWCを有効にする方法

概要 / 方法 / その他

StorybookでEmotion 11がエラーになる問題の解決方法

状況 / 環境 / 解決方法 / 参考

[Next.js] Qiita と Zenn の 記事一覧(フィード)を取得する方法

やりたいこと / 環境 / フィードの仕様 / 実装