【React】state・useStateとは？　stateが更新されるタイミングとは？

# stateとは

- ユーザーの操作や時間経過などにより変化する値。コンポーネントが持つ可変のデータ。
- 別のコンポーネントから直接参照・更新することはできない。
　（別のコンポーネントで扱うには、propsやcontextを使う。）

- stateの状態を管理するにはuseState関数を使う。

# useStateの使い方

useStateを利用するためには、useStateをimportする。

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

useStateの宣言

```jsx
//構文
const [変数名, 関数名] = useState(変数の初期値);

//例
const [count, setCount] = useState(0);
	//setCountメソッドを使ってcountの値を変更することができる
```

この書き方は、JavaScriptの分割代入の構文。

useStateの宣言をすると、useStateからは2つの要素を持つ配列が返される。

1つ目はstateの現在値、2つ目はstateを更新するための関数。

上の例ではcountとsetCountという名前の2つの変数を作り、useStateから返される値のうち1つ目をcountに、2つ目をsetCountに代入する、という意味になる。

参考：[ステートフックの利用法 - React](https://ja.reactjs.org/docs/hooks-state.html#tip-what-do-square-brackets-mean)

# 使ってみる

ローカルでReactの実行環境は作成済みとする。

参考：[React.jsを始めよう：動かしながら仕組みを知ろう](https://code-ship-blog.wemotion.co.jp/technology/react-js%E3%82%92%E5%A7%8B%E3%82%81%E3%82%88%E3%81%86%EF%BC%9A%E5%8B%95%E3%81%8B%E3%81%97%E3%81%AA%E3%81%8C%E3%82%89%E4%BB%95%E7%B5%84%E3%81%BF%E3%82%92%E7%9F%A5%E3%82%8D%E3%81%86/)

```jsx:src/App.js
//useStateを使うためのimport
import React, { useState } from "react"

function App() {

	//stateの初期値をsountに、stateを更新するための関数をsetCountに代入
  const [count, setCount] = useState(0)

	//setCountを使ってcountを更新する関数を定義
  const increment = () => setCount(count + 1)
  const decrement = () => setCount(count - 1)

  return (
    <div>
      <h3>りんごの在庫：{count}個</h3>
      <button onClick={increment}>1つ購入</button>
      <button onClick={decrement}>1つ食べる</button>
    </div>
  )
}

export default App
```


## 機能追加してみる

りんごの在庫が0個になると、「1つ食べる」ボタンは押せなくなり、エラーメッセージが表示されるようにしてみる。

```jsx:src/App.js

import React, { useState } from "react"

function App() {

  const [count, setCount] = useState(0)

	//countが0以下のときtrue、1以上であればfalseになる、disabledを定義
  const disabled = count<=0

  const increment = () =>setCount(count + 1)
  const decrement = () =>setCount(count - 1)

  return (
    <div style={{ margin: "50px" }}>
      <h3>りんごの在庫：{count}個</h3>
      <button onClick={increment}>1つ購入</button>
			{//disabledがtrueのとき、HTMLのdisable属性を有効にする}
      <button disabled={disabled} onClick={decrement}>1つ食べる</button>

      {count <= 0 &&
        <h4 style={{ color: "red" }}>
          りんごを食べ切ったよ！！
        </h4>
      }
    </div>
  );
}

export default App
```

# state更新のタイミング

ただしuseStateを使って値を更新しても、即時にstateの値が変わるわけでは無い。

動きを知るため、先ほどのApp.jsにアラートとコンソール への出力を書き足してみる。

```jsx:src/App.js

import React, { useState } from "react";

const App = () => {
  console.log("App");

  const [count, setCount] = useState(0);
  const disabled = count <= 0;

  const increment = () => {
    setCount(count + 1);
    alert(`りんごが${count}個になったよ！`);       //追記
  };
  const decrement = () => setCount(count - 1);

  console.log(`りんごは今${count}個`);            //追記

  return (
    <div style={{ margin: "50px" }}>
      <h3>りんごの在庫：{count}個</h3>
      <button onClick={increment}>1つ購入</button>
      <button disabled={disabled} onClick={decrement}>
        1つ食べる
      </button>

      {count <= 0 && <h4 style={{ color: "red" }}>りんごを食べ切ったよ！！</h4>}
    </div>
  );
};

export default App;
```

するとアラート時点ではstateの値が更新されておらず、コンソール に表示されるときにはstateの値が更新されている。

更新した後の値を即時に使いたい場合は、useStateで扱うstateをそのまま使うのではなく、更新した値を別の変数として定義する。

```jsx
const increment = () => {
    const newCount = count + 1;
    setCount(newCount);
    alert(`りんごがcount:${count}個、newCount:${newCount}になったよ！`);
  };
```

以下のように関数を切り分けたとすると…

```jsx
const increment = () => {
    const newCount = count + 1;
    setCount(newCount);
    alertCount(newCount);
  };

const alertCount = (newCount) => {
  alert(`りんごがcount:${count}個、newCount:${newCount}個になったよ！`);
  };
```


やはりstateはalertCountを呼び出す時点では更新されていないことがわかる。

## さいごに

### useStateの特徴

- ページをリロードするとstateはリセットされる（初期値になる）
- stateが更新されるごとに、コンポーネントは再レンダリングされる

### レンダリングとは

stateやpropsの変更差分を反映したDOMを再構築すること。

レンダリングが起きると、コンポーネントの頭から処理が順に行われる。

## 参考記事
https://reffect.co.jp/react/react-hook-usestate-understand


https://qiita.com/seira/items/f063e262b1d57d7e78b4