
Reactの場合、useEffectはデバッグ時に二度走る
要素の検証のコンソールに同じ文字列が二行ずつ表示されていて、「なんじゃこりゃ!?」と思った方もいらっしゃるでしょう。
これはバグではなく仕様(Strict Mode)であり、React 18.0.x, 18.1.x, 18.2.x〜で起こることだそうです。
対応方法についての議論は下記リンクにありました。
Bug: useEffect runs twice on component mount (StrictMode, NODE_ENV=development)
2回実行される問題についての対処方法
今回私は、Rust言語を用いたGUIフレームワーク「Tauri」で実際の挙動に出会いましたので、Tauriで同じように躓いている方が解決できるよう記しておきます。
ちなみに使用した雛形はtauri-apps / create-tauri-app v3.4.0 です。
変更を加えるファイルのパスは「/プロジェクト名/src/main.tsx」になります。
変更前
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import "./styles.css";
ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
<react.strictmode>
<app></app>
</react.strictmode>
);
変更後
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import "./styles.css";
ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
// <react.strictmode>
<app></app>
// </react.strictmode>
);
再度要素の検証のコンソールで確認してみてください。きっとうまく対応できているはずです。
React公式によると、
将来的には、React が状態を維持しながら UI のセクションを追加および削除できるようにする機能を追加したいと考えています。たとえば、ユーザーがタブで画面から離れて戻ると、React はすぐに前の画面を表示できる必要があります。これを行うために、React は、アンマウントする前に使用されたのと同じコンポーネント状態を使用して、ツリーの再マウントをサポートします。
この機能により、すぐに使用できる React のパフォーマンスが向上しますが、コンポーネントは、複数回マウントおよび破棄されるエフェクトに対して回復力がある必要があります。ほとんどのエフェクトは何も変更しなくても機能しますが、一部のエフェクトは、destroy コールバックでサブスクリプションを適切にクリーンアップしないか、マウントまたは破棄が 1 回だけであると暗黙的に想定します。
これらの問題を表面化させるために、React 18 では Strict Mode に開発専用の新しいチェックが導入されています。この新しいチェックは、コンポーネントが初めてマウントされるたびに、すべてのコンポーネントを自動的にアンマウントして再マウントし、2 回目のマウントで以前の状態を復元します。
また、これらは開発時にのみ適用されるので、特に本番公開時には問題ないことも触れられています。


Be the first to comment