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

2 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を利用する

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'の判定を入れて開発モードのみの処理にしておく。

参考