React公式ページで学んでみた11（備忘録）

# はじめに
初めまして！
エンジニアになって数年、今まで本を読むだけでしたが、もっとプライベートで楽しみながら成長したい！自分が学んだ足跡を残していきたい！と思い記事を書きました！
最終的には自在に開発できるようになりたいと思っています。:triumph:
いろいろな記事を参考にさせてもらっています。:bow_tone2:
その中でもこれってどういう意味？とかつまづいたところを念入りに書いていこうかと思います。:fist:

# 今回の目的
前回の続きです。今回は「コンポーネント間で state を共有する」。被る部分もあると思いますが、後で振りかえって深掘りするきっかけになるのが理想です。細かく書くと大変なのであっさりめ。

https://qiita.com/mr_noppo/items/ff72d4fe67ec202e67b9

# 使用したものや事前準備
・Macbook Pro
・Visual Studio Code

# 主に参考にさせていただいた記事
https://ja.react.dev/learn/sharing-state-between-components

# リフトアップ
各コンポーネントでstateの状態を共有したい場合、親コンポーネントに情報を持たせる。
lifting state upと言います。

```react
// 複数のPanelコンポーネントがあった場合もisActiveのstateはそれぞれのコンポーネントで管理されるため独立している。
function Panel({ title, children }) {
    const [isActive, setIsActive] = useState(false);
```

親コンポーネントにstateを持たせることで各コンポーネントの状態を管理する
```react
<Panel
    title="About"
    isActive={activeIndex === 0}
    onShow={() => setActiveIndex(0)}
>

function Panel({
  title,
  children,
  isActive,
  onShow
}) {

```

# stateの保持とリセット

## stateはレンダーツリーの位置に結びついている
Reactはstateを保持し、レンダーツリーに沿ってstateを管理します。
コンポーネントが破棄されるときに紐づいたstateも破棄されます。

### 同じ位置のコンポーネントならstateは保持される
下記の場合、タグは分かれているがレンダーツリー上同一なものとみなされstateは保持される。
```react
{isFancy ? (
    <Counter isFancy={true} /> 
) : (
    <Counter isFancy={false} /> 
)}
```
下記の構成でもレンダーツリーが同じのためstateは保持される
```react
if (isFancy) {
    return (
      <div>
        <Counter isFancy={true} />
        <label>
          <input
            type="checkbox"
            checked={isFancy}
            onChange={e => {
              setIsFancy(e.target.checked)
            }}
          />
          Use fancy styling
        </label>
      </div>
    );
  }
  return (
    <div>
      <Counter isFancy={false} />
      <label>
        <input
          type="checkbox"
          checked={isFancy}
          onChange={e => {
            setIsFancy(e.target.checked)
          }}
        />
        Use fancy styling
      </label>
    </div>
  );
}
```

上記の点から、
・同じタグ構成であればstateは保持される。
・少しでも構成が違うと、表示は同じでもコンポーネントが切り替わったり表示されなくなればstateは破棄される


### stateを保持させたくない場合
下記の状態だと、Counterコンポーネントのレンダーツリーが一致するためstateは保持され続ける。
```react
<div>
  {isPlayerA ? (
    <Counter person="Taylor" />
  ) : (
    <Counter person="Sarah" />
  )}
```
コンポーネントのstateが切り替わるルールは二つ
１.コンポーネントを異なる位置でレンダーする
2.key を使って各コンポーネントに明示的な識別子を付与する

#### コンポーネントを異なる位置でレンダー
タグを変えるだけではなく、レンダー時に一時的にタグの表示を消すことで、stateの破棄も可能。
分離して配置しているとstateが破棄されるとも取れる。
```react
    <div>
      {isPlayerA ?
        <Counter person="Taylor" />
      }
      {!isPlayerA &&
        <Counter person="Sarah" />
      }
```

#### key を使って各コンポーネントに明示的な識別子を付与する
keyを使うと識別子になり、コンポーネントのstateが破棄される。関連のあるコンポーネントにkeyを設定することで値が切り替わった時にコンポーネントのstateを破棄するようコントロールできる。

```react
  return (
    <div>
      {isPlayerA ? (
        <Counter key="Taylor" person="Taylor" />
      ) : (
        <Counter key="Sarah" person="Sarah" />
      )}
```

## コンポーネント関数は常に最上位で定義する
下記の状態だたMyComponentが再レンダリングされるたびに、MyTextFieldが再生成され、stateが初期化される。
```react
export default function MyComponent() {
  const [counter, setCounter] = useState(0);

  function MyTextField() {
    const [text, setText] = useState('');

    return (
      <input
        value={text}
        onChange={e => setText(e.target.value)}
      />
    );
  }
```

# 次
https://qiita.com/mr_noppo/items/3529a9e87bf9834db57a