Reactのstateを使いこなそう！

# useStateとは
- コンポーネントの再レンダリングを依頼
- 値を保持する(state)

=> 入力値の変更などに応じて、リアルタイムで画面を再生成することができる

## state
コンポーネントごとに保持される値

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

const Example = () => {
  console.log(useState());
  // => 0: undefined 初期値
  // => 1: ƒ ()　更新用の関数
};
```
以下は、クリックするたびにカウント１増やす例

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

const Example = () => {
  let [val, setVal] = useState(1);
  // valに1、setValに更新用の関数をセット
  console.log(val);

  return (
    <>
      <button onClick={() => setVal(val + 1)}>
        ボタン
      </button>
    </>
  );
};

```

## 注意事項
### 即時反映ではない

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

const Example = () => {
  let [val, setVal] = useState(1);

  const countUp = () => {
    setVal(val + 1);
    console.log(`countUp内のval: ${val}`);
    // => valの値に変更なし
  }
  console.log(`コンポーネント内のval: ${val}`);
  // valが+1されている

  return (
    <>
      <button onClick={countUp}>
        ボタン
      </button>
    </>
  );
};
```
クリックすると、コンソールに以下のように表示される
```console
countUp内のval: 1
Example.jsx:10 コンポーネント内のval: 2
```

更新用の関数を2回読んでも、即時反映されているわけではないので+1しかされない

```jsx
const Example = () => {
  let [val, setVal] = useState(1);

  const countUp = () => {
    setVal(val + 1); // setVal(2)と同じ
    setVal(val + 1); // setVal(2)と同じ
    console.log(`countUp内のval: ${val}`);
    // => countUp内のval: 1
  }
  console.log(`コンポーネント内のval: ${val}`);
  // => コンポーネント内のval: 2

  return (
    <>
      <button onClick={countUp}>
        ボタン
      </button>
    </>
  );
};
```
もし、前の値を利用したい場合は、関数を利用する
```jsx
const Example = () => {
  let [val, setVal] = useState(1);

  const countUp = () => {
    setVal(val + 1);  // setvale(2)
    setVal(preval => preval + 1); // prevalに2が入りsetval(3)になる
    console.log(`countUp内のval: ${val}`);
    // => countUp内のval: 1
  }
  console.log(`コンポーネント内のval: ${val}`);
  // => コンポーネント内のval: 3

  return (
    <>
      <button onClick={countUp}>
        ボタン
      </button>
    </>
  );
};

```
何回でも前の値を利用することができる
```jsx
const Example = () => {
  let [val, setVal] = useState(1);

  const countUp = () => {
    setVal(val + 1);  // setvale(2)
    setVal(preval => preval + 1); // prevalに2が入りsetval(3)になる
    setVal(preval => preval + 1); // prevalに3が入りsetval(4)になる
    setVal(preval => preval + 1); // prevalに4が入りsetval(5)になる
    console.log(`countUp内のval: ${val}`);
    // => countUp内のval: 1
  }
  console.log(`コンポーネント内のval: ${val}`);
  // => コンポーネント内のval: 5

  return (
    <>
      <button onClick={countUp}>
        ボタン
      </button>
    </>
  );
};

```

### オブジェクトの場合
オブジェクトの値を変更するには、新しいオブジェクトを生成し、更新関数に設定する
```jsx
import { useState } from "react";

const Example = () => {
  const countObj = { a: 0, b: 0 };
  const [count, setCount] = useState(countObj);

  const countUpA = () => {
    count.a = count.a + 1;
    setCount(count) // レンダリングされないため、更新できない
  }

  const countUpB = () => {
    setCount({ a: count.a, b: count.b + 1 }) // レンダリングがあり、更新
  }

  return (<>
    <h3>A:{count.a} B:{count.b}</h3>
    <div>
      <button onClick={countUpA}>A</button>
      <button onClick={countUpB}>B</button>
    </div>
  </>);
};
```
スプレット演算子で書くこともできる

```jsx
const Example = () => {
  const countObj = { a: 0, b: 0 };
  const [count, setCount] = useState(countObj);

  const countUpA = () => setCount({ ...count, a: count.a + 1 });
  const countUpB = () => setCount({ ...count, b: count.b + 1 });

  return (<>
    <h3>A:{count.a} B:{count.b}</h3>
    <div>
      <button onClick={countUpA}>A</button>
      <button onClick={countUpB}>B</button>
    </div>
  </>);
};
```