Reactを学ぶ

## Reactを動かす


```html
<!DOCTYPE html>
<html>
<head>
 <script src="/libs/react.development.js"></script>
 <script src="/libs/react-dom.development.js"></script>
 <script src="/libs/babel-standalone.js"></script>
</head>
<body>
    <div id="app"></div>
    <script type="text/babel">
     // jsでタグは読み込まれないので、javascriptのオブジェクトに変換する際にバベルを使ってjavascriptのコードを変換して使用
     const appEl = document.querySelector('#app');
     const root =ReactDOM.createRoot(appEl);
     
     root.render(<h1>こんにちは</h1>);//jsx構文
     //予期せぬ文字列となっている:jsで読み込まれない。
     // v18以降はroot.renderが推奨
     // 下記は非推奨
     // ReactDOM.render(<h1>こんにちは</h1>,appEl);
    </script>
</body>
</html>
```

コンポーネント：
画面の各構成要素をReactで定義したもの

・再利用の向上
・可読性の向上
・疎結合になる（バグの減少）


コンポーネントはJSの関数定義


```javascript
function Welcome(){
return <h1>Hello</h1>;
}

<Welcome />

```


```javascript
<!DOCTYPE html>
<html>
<head>
   <script src="/libs/react.development.js"></script>
   <script src="/libs/react-dom.development.js"></script>
   <script src="/libs/babel-standalone.js"></script>
</head>
<body>
    <div id="app"></div>
    <script type="text/babel">
        const appEl = document.querySelector('#app');
        const root = ReactDOM.createRoot(appEl);
        function Example(){//必ず関数の頭は大文字、小文字だとhtmlのタグと認識される。
         return <h1>Hello Components</h1>; //関数コンポーネント
        }


        // const Example2 =() =>{
        //  return <h1>Hello Components2</h1>
        // }

         // 1行の時
         const Example2 =() => <h1>Hello Components2</h1>
         //複数行の時
        const Example3 =() =>{
        return (
         <div>
          <h1>Hello Components2</h1>
         </div>
        )
        }
        //下記でもOK,{}なしでもreturn のみなので不要
         const Example4 =() => (
         <div>
          <h1>Hello Components2</h1>
         </div>
         )
               
        const a =() =>{
         return   //何も続けなかった場合にjavascriptエンジンが　"return undefined;"のセミコロンが代入されているのと同じことになり、undefineとなり、実行文章が終えることと同じ意味になるため、改行と同じ意味になります。
         // 複数行である場合には()をつけるようにする。
          "戻り値";
        }
        console.log(a())
        root.render(<Example2 />);
    </script>
</body>
</html>
```

## React　立ち上げ

```
# プロジェクトの作成方法
npx create-react-app {プロジェクト名}

# create-react-appドキュメント
npm docs create-react-app

Windowsの方でエラーが発生する方は以下のコマンドを実行してみてください。

```powershell
Set-ExecutionPolicy RemoteSigned
```

# その他
[Vite](https://ja.vitejs.dev/) というモジュールバンドラーを使ったプロジェクトの作成
最近は一般的
```bash
npm create vite@latest
```

```
  "scripts": {
    "start": "react-scripts start",
//開発時に使うコマンドでサーバーを立ち上げアプリを使う
    "build": "react-scripts build",
//本番環境用にビルドするコマンド
    "test": "react-scripts test",
//テストスクリプトを実行するようのコマンド
    "eject": "react-scripts eject"
//隠しファイルを表示する用のコマンド
  },


```


```json
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "lint": "eslint src --ext js,jsx --report-unused-disable-directives --max-warnings 0",
//コードチェック
    "preview": "vite preview"
  },

```



## React スタイル

```html
import "./Example.css";

class MyClass{}//<<JSでは左のように使うため。混同しないように



const Example = () => {
  return (
   <div className="component">
    {/* classではなくclassNmae */}
      <h3>Hello Component</h3>
    </div>
  );
};

export default Example;
```

```css
.App-start .component{
 padding:1rem;
 color:red;

 border:5px solid green
}

/* cssはグローバルになるため、CSSを当てる際には注意が必要 */
```


## パーツを分割


```jsx

import Child from "./component/Child";
// .jsはどちらでも良いwebpackが勝手に解釈してくれる

```

```jsx
import Child from "./components/Child"
const Example = () => <Child />;

export default Example;

```

```jsx
const Child = () => { 
 return (
  <div className="component">
   <h3>Child Component</h3>
  </div>
 );
}
 
//コンポーネントは一つのファイルに一つのコンポーネントが普通
//export default でOK
export default Child 

```

## フラグメント

```jsx
import "./Child.css";
// import React from "react"  //どちらでも良い
//この場合には<React.Fragment>で囲む



import { Fragment } from "react";  //どちらでも良い
const Child = () => {
 return (
  // ルート要素として一つのルートで囲む必要がある。
  // divなど不要なタグで囲まないようにするためにFragmentを使う
  //fragmentは属性をつけることができない
  <Fragment key="">
   {/* キー属性はつけることが可能、ただし、Fragmentのキーワードは省略不可 */}
   {/* <>でOK */}
   <div className="component">
    <h3>Hello Component</h3>
   </div>
   <h3>Hello Fragment</h3>
   <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Obcaecati repellat dolor doloribus iure consequatur soluta? Optio corrupti ratione suscipit recusandae eius perspiciatis illo corporis? Aliquam nam repellendus quos expedita est?</p>
  </Fragment>
 );
};

export default Child;

```


## ReactのJS実行

JSのコード内では波括弧を使ってJAVASCRIPTの指揮を評価してその結果を画面上に表示する。

```jsx
import "./Expression.css"

const Expression = () => {
 const title = "Expression";
 const arry = ['item1', 'item2', 'item3'];
 const hello = (arg) => `${arg} function`; //`${arg}`：テンプレートリテラル
 const jsx = <h3>Helloe JSX</h3>;//Javascriptのオブジェクトとして使われる。
 const bool = true;
 return (
  <div className={title.toLowerCase()}>
   {/* タイトルを使って小文字表示 メソッドも実行可能*/}
   <h3>Hello {title}</h3>
   <h3>Hello {arry}</h3>
   {/* 配列の場合自動的に展開されて表示する */}
   <h3>{hello('Hello')}</h3>
   <h3>{/* 画面上に表示されません。 */}</h3>
   {<h3>Helloe JSX</h3>} 
   {/*これも JS コード 最終的にJSのオブジェクトに変換される。 */}
   {bool} 
   {/* boolearnは表示されない。 */}
  </div>
 );
 //jsのコードを埋め込むことができる。式を埋め込み可能
}
 


export default Expression;
```

## 式と文
JSX内では式しか使うことができない。
式：何らかの値を返すもの（変数に代入できるもの）
文：変数宣言、for文、if文、switch文やセミコロンで区切るもの。

```jsx
import "./Child.css";

const Child = () => {
 const fn = () => 'hello';
 const a =if (true) { 'hello' };//NG
 // if文自体は変数に代入できないものなので文となる。
 const f = fn();
 //関数を実行した結果はhelloという値を返す式となりますので、この関数の実行結果は式
 const c = 1 === 1;
 //式　左オペランドと右オペラんどが等しい場合にはtrue/falseを返す式となります。
 //ただし、表示はされない
 const b = 1;
 // const b = 1;は文になる。
 // 1というのは1という値を返す式、変数に代入できる。
 1;//式にも文にもなりえる 式ぶん

 if (true) { 'hello' };
 // ここでif文はOK
  return (
    <div className="component">
    <h3>式と文</h3>
    {1 === 1} 
    {/* 非表示い */}
    {true ? 'hello' : 'bye'}
    {/* OK */}
    {if (true) {'hello'};}
    {/* NG  for も同様　return内で使わなければOK */}
    </div>
  );
};

export default Child;
```


```jsx
const title = 'Expression';
const array = ['item1', 'item2', 'item3'];
const fn = (arg) => {
  return `${arg} Function`;
};
const upperCaseText = 'upperCaseText';

const Example = () => {
  return (
    <>
      <h3>Hello JSX</h3>
      {/* toUpperCaseメソッドで文字列をすべて大文字にします。 */}
      <h3>{upperCaseText.toUpperCase()}</h3>
      {/* +演算子で文字列を結合します。 */}
      <h3>{'Hello ' + title}</h3>
      {/* 配列がJSX内で渡されると自動的に要素が展開されて表示されます。 */}
      <h3>{array}</h3>
      {/* 関数の実行はreturnに続く値が返ってきます。 */}
      <h3>{fn('Hello')}</h3>
    </>
  );
};

export default Example;
```

## props


```jsx
import Child from "./components/Child";

const Example = () => {
 return (
  <>
  <Child  />
  <Child color="red" />
  </>

)};
// 属性を指定して値を渡すことが可能
export default Example;
```


```jsx
import "./Child.css";
// 外部から値を渡して再利用性を
// const Child = (props) => {
 // propsである必要なし pでも慣習的に暗黙ルール
 
 // 分割代入する場合
const Child = ({ color:c = 'green' }) => {
 // green:初期値設定
 // color:c colorの値をcとして置き換えて使う
 console.log()
 return (
   <>
   <div className={`component  ${c}`}>
      <h3>Hello Component</h3>
    </div>
   </>
  );
};

export default Child;
```

## Props2 
```jsx
import Child from "./components/Child";

const Example = () => {
 const hello = (arg) => `ello ${arg}`;
 const o = {
  color: "red",
  num:123,
 }
 return (
  <>
   {/* <Child /> */}
   {/* <Child color="red" /> →エラー*/}
   {/* 下記でfnを渡すように定義されていることから、呼び出す際にpropsとして関数を渡していないのでfnはundefinedとなり、fn is not a functionとなる */}
   <Child
    {...o}
    // スプレッド演算子でオブジェクトの値が展開される。
    // num={123}
    fn={hello}
    bool
    obj={{ name:'Tom',age:18 }}
    // trueの値が渡ってくる
   />
   {/* 属性が定義されていない分についてはundefinedとなる。 */}
  </>

 )
};
// 属性を指定して値を渡すことが可能
export default Example;


```

```jsx
/* POINT 式と文
式：何らかの値を返すもの（変数に代入できるもの）
文：変数宣言、for文、if文、switch文やセミコロンで区切るもの。
*/

import "./Child.css";
// 外部から値を渡して再利用性を
// const Child = (props) => {
 // propsである必要なし pでも慣習的に暗黙ルール
 
 // 分割代入する場合
// const Child = (props) => {
 // console.log(props)
const Child = ({ color:c = 'green',num, fn,bool,obj }) => {
 // green:初期値設定
 // color:c colorの値をcとして置き換えて使う
 console.log();
 return (
   <>
   <div className={`component  ${c}`}>
      <h3>Hello Component</h3>
      <h3>{num}</h3>
      <h3>{fn('Props')}</h3>
      <h3>{bool ? 'true' :'false'}</h3>
      <h3>{obj.name + obj.age}</h3>
    </div>
   </>
  );
};

export default Child;
```


## チルドレン

```jsx
import Profile from "./components/Profile";
import Container from "./components/Container";

const profile = [
  { name: "Takashi", age: 19, country: "Japan", color: "green" },
  { name: "Jane", age: 28, country: "UK", color: "red" },
];

const Example = () => {
  return (
    <div>
    <Container title="Childrenとは？" >
     <Profile {...profile[0]} />
    </Container>
    </div>
  );
};

const Example2 = () => {
 return (
  <div>
   <Container title="Childrenとは？" children={
    [<Profile key={profile[0].name} {...profile[0]} />,
     <Profile key={profile[1].name} {...profile[1]} />]
   } first={<Profile key={profile[0].name} {...profile[0]} />}
    second={<Profile key={profile[1].name} {...profile[1]} />}
   />
    {/* 上記の表現でも問題なし、このコンポーネント自体もjavascriptのオブジェクトになりますので、この列に格納することができます。 */}

  </div>
 );
};

export default Example2;


```


## propsのルール
// POINT propsの流れは一方通行 親から子へ
// POINT propsは読み取り専用

```jsx
import Bye from "./components/Bye"
import Hello from "./components/Hello"

const Example = () => {
 const name = "Tom";
  return (
    <>
    <Hello name={ name } />
    <Bye name={name } />
    </>
  );
};

export default Example;

```


```jsx
const Hello = (props) => {
 // props.name = 'BOb';// エラー読み取り専用props

 const desc = Reflect.getOwnPropertyDescriptor(props, 'name');
 console.log(desc);
 // configurable:false;変更できるか？できない
 // writable:false;書き換え可能か？不可
  return (
    <div>
      <h3>Hello {props.name}</h3>
    </div>
  );
};

export default Hello;
```

```jsx
const Bye = (props) => {
 const name = 'Tom';
 // Helloへは渡せない
 // 親コンポーネント
  return (
    <div>
      <h3>Bye {props.name}</h3>
    </div>
  );
};

export default Bye;

```

## jsxの正体


babelにて関数に置き換えられ、オブジェクトになる。


JSXはJSのオブジェクトに変換される。
JSオブジェクト（React要素）

```JSX
  const sample2 = (
    <div>
      <h1>Hello!</h1>
      <h2>Good to see you.</h2>
    </div>
  );
```
Babel変換
```jsx
  const sample2 =React.createElement(
    "div",//タグ名
   null,// プロップスの値
   React.createElement("h1", null, "Hello!"),
    
    React.createElement("h2", null, "Good to see you.")
  );
```

実行結果
```jsx
const element ={
 type:'h1',
 props:{
  className:'greeting',
  children:'Hello World'
}
};
```

## 開発で利用するイベントについて

```jsx
const Example = () => {
 const clickHandler = () => {
  alert('ボタンがクリックされrました。');
  // 戻り値returnがないのでundefinedの戻り値が返ってくる。
 }
 // 極力名前付き関数を定義してから下記に入力
 
 const hello = () => 'hello react';
 console.log(hello)
 // () => 'hello react'がそのまま表示される。
 console.log(hello());
 // hello reactが表示される。

 return (
   <>
   <button onClick={clickHandler}>クリックしてね</button>
    {/* onClickのCは大文字 */}
   {/* clickHander()（関数を実行したもの）と()をつけるわけではなくclickHandler(ボタンを押されて実行するもの)として記載する。 */}
   <button onClick={() => clickHandler()}>クリックしてね</button>
   {/* 上記の場合には関数の実効記載が必要。クリックされてから関数が実行するため、実行されたreturnには()を付けないと関数が戻り値となってしまう。 */}
   <button>クリックしてね</button>
   {hello()}
   </>
  );
};

export default Example;
```


```jsx
import "./Example.css";

const Example = () => {
  return (
    <div>
      <h3>コンソールを確認してください。</h3>
      <label>
        入力値のイベント：
        <input
          type="text"
      onInput={() => console.log("onChange検知")}
      //JSにおけるonInputがReactのonChangeイベントと同じ（変更された時に発火する）ようになる
      // 通常JSではonchangeイベントは入力を終えてフォーカスが外れた時に動作する。
      onBlur={() => console.log("onBlur検知")}
      // 入力欄からフォーカスが消えた時を検知
      onFocus={() => console.log("onFocus検知")}
      // 入力欄からフォーカスを得た時を検知
        />
      </label>
      <div>
        <label>
          入力値を取得：
          <input type="text" onChange={(e) => console.log(e.target.value)} />
        </label>
    </div>
    {/* マウスホバー時を検知 */}
      <div
     className="hover-event"
     
     onInput={() => console.log("カーソルが入ってきました。")}
     onChange={() => console.log("カーソルが入ってきました。")}
        onMouseEnter={() => console.log("カーソルが入ってきました。")}
        onMouseLeave={() => console.log("カーソルが出ていきました。")}
    >

        ホバーしてね！
      </div>
    </div>
  );
};

export default Example;
```


## useState

```jsx
import { useState } from "react";
const Example = () => {
 let valArry = useState("hello");
 let [val, setVal] = useState('hello');
 // [0,f]
 //配列の0番目に参照用の値が渡ってきます。
 // 配列の0番目：参照用の値
 // 配列の1番目：更新用の関数
 // 初期値0
 // 読み込み用と
 console.log(valArry)

 return (
  <>
   <input
    type="text"
    onChange={(e) => {
     // const setFn = valArry[1];
     setVal(e.target.value)
     // 更新されない
    }} /> = {val}
  </>
 );
};

export default Example;
```

変数の値を変えても画面の表示は変わらない理由
・Reactにコンポーネントの再実行（再レンダリング）を依頼し、新しいReact要素を作成してもらう必要がある。
・変更した値をどこかに保持しておく必要がある。（stateに保存）
これらを可能にする仕組みが  <strong>useState</strong>
```jsx
import { useState } from "react";

const Example = () => {
 let displayVal;
 //2. Exampleが実行されるたびに値が空になってしまう。
  let [ val, setVal ] = useState();
  console.log('再レンダリングされました');
  return (
    <>
      <input
        type="text"
        onChange={(e) => {
          console.log(e.target.value);
          setVal(e.target.value);
          //1. displayVal = e.target.value; onChangeにおってコードが実行される
         }}
      />
    = {val}{/* このコードはExample()が実行されないと変わらない/3.さらにExampleが実行されると2の挙動で空が反映される。 */}
    </>
  );
};

export default Example;

```

１.接続hook Into
React内部と接続。状態が管理されるようになる。
2現在の値と更新関数を返却
3.更新関数で新しい値をReactに渡す。また、Reactに自身のコンポーネントを再実行するように依頼する。

useStateはコンポーネントごとに保持


```jsx
import { useState } from "react";

const Example = () => {
 let displayVal;
 //2. Exampleが実行されるたびに値が空になってしまう。
  let [ val, setVal ] = useState();
  console.log('再レンダリングされました');
  return (
    <>
      <input
        type="text"
        onChange={(e) => {
          console.log(e.target.value);
          setVal(e.target.value);
          //1. displayVal = e.target.value; onChangeにおってコードが実行される
         }}
      />
    = {val}{/* このコードはExample()が実行されないと変わらない/3.さらにExampleが実行されると2の挙動で空が反映される。 */}
    </>
  );
};

export default Example;
```


```jsx
import { useState } from "react";

const Example = () => {
 // let displayVal;
 //2. Exampleが実行されるたびに値が空になってしまう。
  let [ val, setVal ] = useState();
  console.log('再レンダリングされました');
  return (
    <>
      <input
        type="text"
        onChange={(e) => {
          console.log(e.target.value);
          // displayVal =e.target.value
          setVal(e.target.value);
          //1. displayVal = e.target.value; onChangeにおってコードが実行される
         }}
      />
    {/* = {displayVal} */}
    {/* Stateを利用しないと再レンダリングされない */}
    = {val}
    {/* このコードはExample()が実行されないと変わらない/3.さらにExampleが実行されると2の挙動で空が反映される。 */}
    </>
  );
};

export default Example;```

```jsx
import { useState } from "react";
const Example = () => {
 console.log(<Example />)
 // _owner FiberNode
 // memorizedStateにて値が保持される。
 // 次の値はnextに入っている。
 const [btnValA, setValA] = useState(0);
 // コンポーネントのトップレベルしか呼ぶことができないuseState
 // if,for,whileなど{}文内においても使用できない。
 // setValAの関数と紐付けされたbtnValAが更新される
 const [btnValB, setValB] = useState(10);
 // 順番で定義されたもの保持されるuseState
 const [ btnValC, setValC ] = useState(100);
 
 const btnCountUp = () => { 
   setValA(btnValA + 1);
 }
 const btnCountUpB = () => { 
   setValB(btnValA + 1);//更新されない
 }
 const btnCountUpC = () => { 
   setValC(btnValC + 1);
 }

 return (
  <>
   <p>ボタンAを{btnValA}回押しました！</p>
   <button onClick={btnCountUp}>ボタンA</button>
   <p>ボタンBを{btnValB}回押しました！</p>
   <button onClick={btnCountUpB}>ボタンB</button>
   <p>ボタンAを{btnValC}回押しました！</p>
   <button onClick={btnCountUpC}>ボタンA</button>
  </>
 );
};

export default Example;


```


```jsx
import { useState } from "react";

const Example = () => {
 const [count, setCount] = useState(0);
 const countUp = () => {
  setCount(count + 1);//:値は1//非同期処理となる。
  setCount(count + 1);//:値は1
  setCount(p => p + 100);//:値は101 関数の引数は前の関数の結果
  setCount(p => p + 1);//:値は1
  console.log(count);
 }
 const countDown = () => {
  setCount(count - 1);
  
 }
 return (<>
  <p>現在のカウント数:{count}</p>
  <button onClick={(countUp)}>+</button>
  <button onClick={(countDown)}>-</button>
 </>);
  
};

export default Example;
```



## useStateの注意点
useStateの関数については予約という考え方のため、
即時処理が行われない。
そのため、関数の実行する際に現在の状況を反映させたい場合には、
set関数内に関数を設置することで値を引用して更新される。
```jsx
import { useState } from 'react';

const Example = () => {
  const [count, setCount] = useState(0);
  
  const countUp = () => {
   setCount(state => state + 1);
   // 現在の値を見て行う場合が多いので常時上記の使い方で実施
  };

  const countDown = () => {
    setCount(state => state - 1);
  };
  return (
    <>
      <h3>練習問題</h3>
      <p>現在のカウント数: {count}</p>
      <button onClick={countUp}>+</button>
      <button onClick={countDown}>-</button>
    </>
  );
};

export default Example;

```

## オブジェクト型のuseStateの注意点


// POINT プリミティブ型：1, "str", bool, 10n, Symbol(), null, undefined
// POINT オブジェクト型：{}, []などのプリミティブ型以外
// POINT オブジェクト型のstateを変更する場合には必ず新しいオブジェクトを作成する！


```jsx
import { useState } from "react";

const Example = () => {
 const personObj = { name: "Tom", age: 18 };
 const [person, setPerson] = useState(personObj);
 const changeName = (e) => { 
  setPerson({ name: e.target.value, age: person.age });
  // setPerson({ name: e.target.value, age: person.age });
  // ageプロパティを消してしまうと更新されてしまうので、setPersonを実行する際には必ず同じ構造で記載すること。
  }
 const changeAge = (e) => { 
  setPerson({ name: person.name, age:e.target.value });

 }
 const reset = () => { 
  setPerson({ name: "", age: "" });
  }
 return (
  <>
   <h3>Name:{person.name}</h3>
   <h3>Age:{person.age}</h3>
   <input type="text" name="" onChange={changeName} id="" value={person.name} />
   <input type="number" name="" onChange={changeAge} id="" value={person.age} />
   <div>
    <button onClick={reset}>リセット</button>
   </div>
  </>

 );
};

export default Example;
```


## オブジェクトのuseStateについて

```jsx
import { useState } from 'react';

const Example = () => {
  const orderObj = { item: 'apple', count: 10 };
  const [order, setOrder] = useState(orderObj);
 const changeItem = (e) => { setOrder({ ...order, item: e.target.value }) };
 // スプレッド演算子で展開
 const countUp = () => {
  setOrder((order) => ({ ...order, count: order.count + 1 }));
  // 配列に()をつけるのは配列がオブジェクトリテラルなのか、あろー関数の関数式か不明であるため、オブジェクトを返す場合には()入れる。
  };
 const countDown = () => {
  setOrder((order) => ({ ...order, count: order.count - 1 }));
  };
  return (
    <div>
      <h3>練習問題</h3>
      <p>
        記述を変更し、完成コードのように「+と-ボタンをクリックするとCountの表示が1ずつ増減する機能」と「input要素に連動してItemの表示が変更される機能」を実装してください。コンポーネントの外側（上部）に変数や関数を準備しているためうまく使ってください。
      </p>
    <h3>Item:{order.item}</h3>
      <h3>Count:{order.count}</h3>
      <input type="text" value={order.item} onChange={changeItem} />
      <button onClick={countUp}>+</button>
      <button onClick={countDown}>-</button>
    </div>
  );
};

export default Example;

```


## 配列のuseState

```jsx 
import {useState} from "react"
const Example = () => {
  const numArray = [1, 2, 3, 4, 5];
 const [nums, setNums] = useState(numArray);
 console.log(nums);
 const shuffle = () => {
  const newNums = [...nums];
  // スプレッド演算子として定義する。新しい配列として定義する。
  // newNums =numsは配列がコピーではなく、配列の参照をコピーしている。
  const value = newNums.pop();
  newNums.unshift(value);
  setNums(newNums);
  // 配列の末尾が削除
  console.log(newNums)
 }
  return (
    <>
    <h1>{nums}</h1>
    {/* {}で展開されると並んで表示される。 */}
    <button onClick={shuffle}>shuffle</button>
    </>
  );
};

export default Example;
```

## State

State はコンポーネント毎に保持

コンポーネントに紐づく値はそれぞれ独立して管理される。

React要素のツリー内の位置によってどのコンポーネントのstateか識別している。


コンポーネントのReact要素ツリーにおける位置が変わらない場合はstateは保持される。
しかし、keyをつけることによって同じ位置の同じコンポーネントでも別物と認識させられる。


```jsx
import { useState } from "react";
const Example = () => {

 const [toggle, setToggle] = useState(true);
 const toggleComponent = () => { 
  setToggle(prev => !prev)
  }
 return (
  <>
   <button onClick={toggleComponent}>toggle</button>
   {toggle ? <Count title="A" /> : <Count title="B" />} 
   {/* 上記の内容では表示位置が変わらない */}
   {/* stateの値を引き継ぐ、同じ位置で切り替わる場合について */}
   {toggle ? <Count title="A" /> : <div><Count title="B" /></div>}
   {/* 上記の場合にはdivがBに追加されているためツリー構造が変わることから値が引き継がれない */}
   <Count title="A" />
   {toggle && <Count title="B" />}
   {/* 上記の場合にはコンポーネントが消滅するため、値が初期化される。 */}
   {toggle ? <Count key="A" title="A" /> : <Count key="B" title="B" />} 
   {/* 上記のコンポーネントが値を別々にしたい場合にはkeyという属性を設定することで、一意のコンポーネントの値を管理できる。 */}
  </>
 )
}
const Count = ({ title }) => {
  const [count, setCount] = useState(0);
  const countUp = () => {
    setCount((prevstate) => prevstate + 1);
  };
 const countDown = () => {
    setCount(count - 1);
  };
  return (
    <>
      <h3>{title}: {count}</h3>
      <button onClick={countUp}>+</button>
      <button onClick={countDown}>-</button>
    </>
  );
};

export default Example;
```

## stateをpropsで渡すケース

・コンポーネントが消滅する可能性がある時
・特定のstateを複数の子コンポーネントで共有したいとき


```jsx
import { useState } from "react";

const Example = () => {
 const [toggle, setToggle] = useState(true);
 const [countA, setCountA] = useState(0);
 const [countB, setCountB] = useState(0);
  const toggleComponent = () => {
    setToggle(prev => !prev);
  }
  return (
    <>
    <button onClick={toggleComponent}>toggle</button>
    {/* {toggle ? <Count key="A" title="A" count={count} setCount={setCount} /> : <Count key="B" title="B" count={count} setCount={setCount} />} */}
    {/* 定義したSTATEをpropsで渡す（値を共有する） */}
     <Count key="A" title="A" count={countA} setCount={setCountA} /> 
     <Count key="B" title="B" count={countB} setCount={setCountB} />
    </>
  )
}
const Count = ({ title,count,setCount }) => {
  
  const countUp = () => {
    setCount((prevstate) => prevstate + 1);
  };
  const countDown = () => {
    setCount(count - 1);
  };
  return (
    <>
      <h3>{title}: {count}</h3>
      <button onClick={countUp}>+</button>
      <button onClick={countDown}>-</button>
    </>
  );
};

export default Example;
```

useState:値と際レンダリングを依頼

・コンポーネントの中で呼び出す。

・if文やfor文の中で呼び出さない

・値の更新と再レンダリングは予約（非同期される）