React useEffectを利用したウィンドウタイトルの変更

# 成果物
useEffectを使用してウィンドウのタイトルを変更する
成果物画面の左下にあるOpen review in new windowをクリックすると新しいタブが開きます。
画面のセレクトボックスを選択するとウィンドウのタイトルがセレクトボックスで選択した値に変更されます。

https://codesandbox.io/embed/useeffect-arenzi-45s5sj?fontsize=14&hidenavigation=1&theme=dark

# useEffect
`useEffect()`は`useEffect()`に渡された関数の実行タイミングを、コンポーネントのマウント後、アンマウント後、または更新後まで遅らせることができるフックです。

- [ ] マウント
コンポーネントに対応するDOMノード（DOMツリーの１つひとつのオブジェクト）を作成し、既存のDOMツリー（画面に表示するために解釈されたHTML、CSS、JavaScriptによって構築されたDOMツリー）に挿入して最終的なUIに出力するプロセス

- [ ] アンマウント
DOMノードが既存のDOMツリーから削除されること

- [ ] 更新
既存のDOMツリーに存在するDOMノードに変更を加えること

## 副作用
Reactにおける副作用とはUI構築以外の処理を指します。例えば、Reactの管理外でDOMを更新する処理、APIとの非同期通信等のデータ取得などが挙げられます。

## 副作用を制御するためにuseEffectを利用する
`useEffect()`により副作用の実行タイミングはブラウザが描画し終えるまで遅延される。つまり、`useEffect()`により実行される副作用のタイミングはUI構築後に行われます。
Reactは副作用が実行されるタイミングで正しくDOMが更新されていることを保証します。`useEffect()`に渡されたコールバック関数は描画完了のタイミングで実行されるため、正しく構築されたDOMを参照することができます。

## useEffect()の基本構文
```javascript
// 関数を定義
const sampleFunc = () => console.log("関数を定義")

// 第1引数には実行させたい関数を定義、第2関数には第1引数に定義した
// 関数の実行タイミングを制御する依存配列を渡す
useEffect(sampleFunc, [依存配列])
```

| 引数     | 説明 | データ型 |
|:-:      |:-:|:-:|
| 第1引数  | 関数（戻り値はクリーンアップ関数、またはなし）  | 関数  |
| 第2引数  | 第1引数の関数の実行タイミングを制御する依存配列  | 配列  |

第2引数は省略することが可能ですが、省略した場合、コンポーネントがレンダリングされる度に第1引数に渡した関数が実行されてしまうため、第2引数を省略するケースはほとんどありません。

## クリーンアップ関数
`useEffect()`の第1引数の関数から返された関数を`クリーンアップ関数`といいます。クリーンアップとはタイマーのキャンセル処理やイベントリスナの削除などで、コンポーネントがアンマウントした時、第1引数の関数が再実行された時に実行される

## useEffectの依存配列
第1引数に渡された関数を初回レンダリング時のみ一度だけ実行させたい場合、第2引数に空の依存配列`[]`を渡します。
```javascript
// 関数を定義
const sampleFunc = () => console.log("関数を定義")

// 初回レンダリング時のみ第1引数の関数を利用したい場合、第2引数に空の依存配列[]を渡します
useEffect(sampleFunc, [])
```

コンポーネント内で`useEffect()`を利用すると、第1引数の関数内から`state`や`props`にアクサスすることができます。第1引数の関数が`state`や`props`に依存していない場合、第2引数は空の配列になります。

## 依存配列の要素の値が変化した場合のみ第1引数の関数を実行させる
```javascript
// 関数を定義
const sampleFunc = (props) => {
    document.title = `私の名前は:${props.name}です`
}

// コンポーネントの初回レンダリング時及び、
// 依存配列内のnameがに変化があった場合のみ第1引数の関数が実行される
useEffect(sampleFunc, [name])
```

# コード
## index.js
```javascript
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>
);
```

## App.js
```javascript
// useEffectを利用するためにimportする
import React, { useState, useEffect } from "react";
import "./styles.css";

// セレクトボックスの要素を設定
const items = [
  { id: 1, item: "おはようございます" },
  { id: 2, item: "こんにちは" },
  { id: 3, item: "こんばんは" }
];

// map()を用いて配列の要素を１つひとつ割り当てていく
const sampleOption = items.map((item) => {
  return (

    // セレクトボックス内で一意の値をkey属性に設定
    <option key={item.id} value={item.item}>
      {item.item}
    </option>
  );
});

const SampleComponent = () => {

  // セレクトボックスで現在選択されているvalue、valueを更新する関数useStateを設定
  const [value, setvalue] = useState(items[0].item);

  // useEffectにより実行される関数sampleFuncを定義
  const sampleFunc = () => {
    
    // ウィンドウのタイトルを変更する
    document.title = `タイトル:${value}`;
  };

  // 初回の画面レンダリング時、第2引数の依存配列に設定されているvalueに変更があった際に
  // 第1引数の関数sampleFuncが実行される
  useEffect(sampleFunc, [value]);

  // セレクトボックスで選択された値(value)を状態変数valuenに設定する
  const handleChange = (e) => {
    setvalue(e.target.value);
  };

  return (
    <div className="App">
      <p>現在のタイトル:{value}</p>
      
      // セレクトボックスに変更があった際に関数handleChangeを実行する
      <select onChange={handleChange}>{sampleOption}</select>
    </div>
  );
};

export default function App() {
  return <SampleComponent />;
}
```

## styles.css
今回は記述なし