結論
クリーンアップ処理が欠けている場合がほとんどのため、クリーンアップ処理を追加すると直る。
例:
useEffect(() => {
const connection = createConnection();
connection.connect();
+ return () => {
+ connection.disconnect();
+ };
}, []);
なぜこういう動きになっている?
React18では、開発チームが意図的にコンポーネントを2度、マウントしている。(Strictモードの開発環境のみ)
つまり、初回マウント→アンマウント→マウントの流れになる。
具体的な理由については、以下の記事で詳しく書かれているのでここでの説明は省きます。
React18でのStrictモードとuseEffectの挙動
Strictモードを解除したり、useRefなどで一回だけ発火させたりすることで、この問題は見かけ上解消されます。
ただ、望ましい解消案は、「useEffectを一回だけ走らせる」ではなく、「2回のマウントでもちゃんと正しく動くコードを書く」ことである。
公式にも関連のことが書かれている。
my-effect-runs-twice-when-the-component-mounts
さいごに
こういう挙動になっていることで、クリーンアップ処理の書き忘れとか、コードのアラに気づけるので個人的にはありがたいです。
解消方法に困っているどなたかの役に立てれば幸いです。