useEffect の使い方を学んでみた

# useEffect とは
React のフックのひとつ。
React コンポーネントのレンダリング後に副作用（サイドエフェクト）を実行するための仕組みを提供するもの。

# useEffect のドキュメントを読んでみる
[react公式ドキュメント > useEffect](https://ja.react.dev/reference/react/useEffect#usage)

## リファレンス
```jsx
useEffect(setup, dependencies?)
```

### 引数
#### `setup`
 - エフェクトのロジックを記述する
 - オプションで、クリーンアップ関数を返すことができる
 - 実行タイミングは、コンポーネントが初めて DOM に追加されたとき
 - 依存配列が変更された場合の再実行時、React は古い値でクリーンアップ関数（あれば）を実行し、次に新しい値でセットアップ関数を実行する

#### `dependencies?`
 - セットアップ関数内で参照されるすべてのリアクティブな値（`props`、`state`、直接宣言された変数や関数）のリスト
 - React は `Object.is` で依存値を前回の値と比較し、変更があれば再実行する
 - 依存配列の指定方法
   - **省略:** 毎回のレンダー後に再実行される
   - **空配列:** 初回レンダー後に1回だけ実行され、その後は実行されない

### 戻り値
 - `undefined`

### 注意点
 - **フックの使用制限:** `useEffect` はコンポーネントのトップレベルやカスタムフック内でのみ呼び出せ、ループや条件文内では使用できない
 - **エフェクトが不要な場合:** 外部システムと同期しない場合、エフェクトは不要
 - **`Strict Mode`:** `Strict Mode` が有効な場合、セットアップ前に開発用のセットアップ+クリーンアップが1回追加される
 - **オブジェクトや関数の依存:** オブジェクトや関数を依存配列に含めると、不要な再実行が発生することがある。不要な依存を削除し、非リアクティブなロジックを外に出す
 - **視覚的な遅延が目立つ場合:** 視覚的な作業を行うエフェクトは、`useLayoutEffect` に置き換えると、描画前に実行されるので遅延が減る
 - **ユーザ操作によるエフェクト:** ユーザ操作がトリガーの場合、React は通常の動作とは異なり、ブラウザが更新後の画面を描画する前にエフェクトを実行することがある。描画後に処理を遅らせたい場合は `setTimeout` を使用する
 - **クライアント上でのみ実行:** `useEffect` はクライアント上でのみ実行され、サーバサイドレンダリング中には実行されない

## 使用法

### 外部システムへの接続
コンポーネントが外部システム（ネットワーク、ブラウザAPI、サードパーティライブラリなど）と接続する場合、useEffect を使用する。
外部システムは React によって制御されない。

#### `useEffect` の基本構造
- 第一引数：セットアップ関数を含む関数
- 第二引数：依存値のリスト（エフェクト内で使用されるすべてのコンポーネントの値を含む）
- セットアップ関数はクリーンアップ関数を返す必要がある

#### `useEffect` の動作タイミング
- **マウント時:** セットアップ関数が実行される
- **再レンダー時:**
  1. 古い依存値でクリーンアップ関数が（あれば）実行される
  2. 新しい依存値でセットアップ関数が実行される
- **アンマウント時:** 最後にクリーンアップ関数が（あれば）実行される

#### 例
```jsx
import { useEffect } from 'react';
import { createConnection } from './chat.js';

function ChatRoom({ roomId }) {
  const [serverUrl, setServerUrl] = useState('https://localhost:1234');

  // useEffect はコンポーネントがレンダリングされた後に実行される副作用（エフェクト）を設定する
  useEffect(() => {
  	const connection = createConnection(serverUrl, roomId);   // createConnection を呼び出して、serverUrl と roomId を使って接続を作成する
    connection.connect();   // connection.connect() を呼び出して、実際に接続を確立させる

    // クリーンアップ関数の開始
    // コンポーネントがアンマウントされるときや依存値が変更されるときに実行される
  	return () => {
      connection.disconnect();   // connection.disconnect() を呼び出して、接続を切断する
  	};
  }, [serverUrl, roomId]);   // serverUrl と roomId が変更されるたびに再実行される
  // ...
}
```

#### 開発環境での動作
- `Strict Mode`が有効な場合、React はセットアップとクリーンアップを余分に1回実行して、ロジックが正しく実装されているかを確認している
- セットアップとクリーンアップが対応していれば、問題が起きない設計にする必要がある

#### 注意点と推奨事項
- 各エフェクトは独立したプロセスとして記述する（例: データ取得、イベントリスナーの登録、DOM 操作など異なる目的の副作用は、1つの `useEffect` にまとめず、必要に応じて分ける）
- マウント、更新、アンマウントの状態を意識せず、セットアップとクリーンアップの対応関係に集中する
- 外部システムと接続しない場合、`useEffect` は不要

#### 使用例
- タイマー (`setInterval` と `clearInterval`) の管理
- イベントサブスクリプション (`addEventListener` と `removeEventListener`) の管理
- サードパーティライブラリの初期化とリセット (`animation.start` と `animation.reset` など)

# まとめ
`useEffect`は、React コンポーネントのレンダリング後（仮想 DOM が更新され、必要に応じて実際の DOM が変更された後）に、副作用（データの取得、サブスクリプションの設定、DOM の直接操作など）を実行するための仕組みである。

# おわりに
ドキュメントのボリュームが多くて途中で断念してしまった。
説明が重複している箇所も多く、読みづらかった〜・・・。
学びとしては、`useEffect` って非同期処理があるときに使うものだとばかり思っていたけど、実は違っていたことに気づけたこと。「画面描画後の副作用を管理するための仕組み」でした。
おそらく私の勘違いの要因は、今まで `useAsync` を使ったことがなくて、バックエンドからデータを取得するときに `useEffect` を使っていたからだと思う。使い方としては間違ってないけど、それ以外の使い方をしたことがなかったから、`useEffect = 非同期処理` みたいな印象があったんだと思う。
`useEffect`は「状態や依存関係の変化に応じて、適切にリソースを管理する仕組み」が本質なんですね。
もやもやが晴れて爽やかな気持ちになりました😊