【React】React 初心者でも useState を完全に理解できる

# 1.はじめに

最近 TypeScript の記事を書き始めてだいぶ　JavaSrcipt や TypeScript の苦手意識は減りましたが、React は難しいなと感じる今日この頃です。

Reactの基礎がわかっていないなと感じ Hook 関係の記事を書いて基礎力をつけたいなと思い本記事を書き始めました。

記事を書くことで React の苦手意識も克服したいなと思っています。

第一弾として、`useState` についてキャッチアップしたので記事にします。

同じように React に抵抗感を持たれてる方に読んでいただけますと幸いです。

したがって、本記事は React の **超** 基礎の記事となっています。

もし間違って認識しているところ等ありましたらご指摘いただけますと幸いです。


# 2.目次

[1.はじめに](#1はじめに)  
[2.目次](#2目次)  
[3.この記事でわかること](#3この記事でわかること)  
[4.環境](#4環境)  
[5.useState とは](#5usestateとは)  
　[5.1.state とは？ Hookとは?](#51stateとは-hookとは)  
　[5.2.useState とは](#52usestate-とは)  
　[5.3.useState の更新関数の引数](#53usestate-の更新関数の引数)  
[6.おわりに](#6おわりに)  
[7.参考](#7参考)  


# 3.この記事でわかること

本記事を読むことで React の Hook の苦手意識をなくすことができます。

- Hook の役割を理解できる
- `usestate` の挙動を理解できる
- `useState` を使えるようになれる


読み終える頃には 「`useState` 完全に理解した！！」と言えるようになっているはずです。


# 4.環境

- React: 17.0.2
- TypeScript: 4.4.2


# 5.useStateとは

Hook や state とはどんなものかの概要を理解してから `useState` に入る方がいいと思いますので、  
まずは、そこから抑えていきましょう。  

## 5.1.stateとは？ Hookとは?

まず、 `useState` の説明に入る前に、**state** や **Hook** とは何かについて振れておきます。

**state** とは、
- コンポーネント（再利用できる部品）の描画（ブラウザに表示）後に変更する値のこと  


**Hook** とは、
- コンポーネントとは独立した関数
- コンポーネントに対して着脱可能な機能を取り付ける（hook up）もの
- 関数コンポーネントで state を実装するときに使う

今回は、コンポーネントに state を追加する　`useState` についての触れていきたいと思います。

Hook の基礎の基礎であろう `useState` がどんな動きをするのか全くわかっていませんでした。

同じ境遇をお持ちの方に読んでいただけると幸いです。

## 5.2.useState とは

今回はクリックしたら数が増える `Counter` というコンポーネントを用いて `useState` がどのような動きをするのかを見ていきたいと思います。

ソースは以下の通りです。

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

export const Counter = () => {
  // useState フックを使ってクリックの回数をステート管理
  const [count, setCount] = useState<number>(0);

  return (
    <div>
      <p>{count} 回クリックしました。</p>
      <button onClick={() => setCount(count + 1)}>Click me</button>
    </div>
  );
}
```

`useState` はこのように配列の分割代入を用いて記述します。

```tsx
const [count, setCont] = useState<number>(0);
```

（分割代入をキャッチアップするまでは、このソースコードの意味が全くわかりませんでしたね…）

以前、分割代入の記事を書いたので、そちらを読んでいただけると分割代入の理解が深まるかと思います。

https://qiita.com/daishiman/items/324dcc0eae72eb6b13cf

それでは、`useState` を読み解いていきましょう。

```tsx
const [count, setCont] = useState<number>(0);
```

`useState` は、この部分ですね。

まずは、`useState<number>(0)` ですが、
- state の引数は number 型
- state の初期値は 0

という意味になります。

（初期値 0 を定義していなかった場合は、undefined となります ）

次に `useState` の式全体を見てみます。

```tsx
const [count, setCont] = useState<number>(0);
```

は、配列の分割代入を使っているので、

```tsx
// この ０ は useState<number>(0) の 初期値 0 ではなく、0 要素目という意味
const count = useState[0]; 
const setCount = useState[1];
```

ということで、つまり　

- `useState` の 0 番目の要素が変数 `count` に代入される
- `useState` の 1 番目の要素が変数　`setCount` に代入される

と同じ意味になります。

この 2 行分の式を **分割代入** で省略して 1 行で書かれています。

この変数名は任意で問題ありませんが、

- 0 番目の要素の変数名は、state の内容に合った名前を使う（今回は `count`）
- 1 番目の要素の変数名は、`set` + 0 番目の要素名を使う（今回は `setCount`）

とするのが一般的です。

どういう構成をしているのかがわかったので、  
`useState` の 0 番目の要素と 1 番目の要素がどのような動きをしているか見てきましょう。

- 0 番目の要素（`count`）には、**state の値** が代入される
- 1 番目の要素（`setCount`）には、**state 値を更新する関数** と **コンポーネントを再描画させる** 役割

となっています

:::note info

今までの内容をまとめると、
- `count` の初期値が0
- `setCount` 関数を呼び出すことで `Counter` 関数コンポーネントが呼び出されて再描画する
- `setCount` の関数で値が変わる毎に `count` の値が更新される
- `count` には更新された state の値が代入される

:::

ということになります。

では、今回のソースコードの流れを追っかけてみましょう。

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

export const Counter = () => {
  // useState フックを使ってクリックの回数をステート管理
  const [count, setCount] = useState<number>(0);

  return (
    <div>
      <p>{count} 回クリックしました。</p>
      <button onClick={() => setCount(count + 1)}>Click me</button>
    </div>
  );
}
```

下記は、`Counter` コンポーネントが呼び出されてからの state の値の流れです。

1. 初期値 0 が `count` に代入される
2. Click me ボタンをクリックすると `setCount` 関数呼び出される
3. `setCount` 関数に `count` （最初は初期値 0）が渡され、`count + 1` の処理を行う
4. `Counter` コンポーネントが再度呼び出され描画する
5. `setCount` 関数の引数の **`count + 1`** が `count` に代入され `count` を更新する
6. 以降 2 ~ 5 を繰り返す

![useState修正.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/756415/9ba57202-0127-5227-0751-f64359c2c45c.png)

これで、`useState` を使ってクリックすると数字が +1 されるロジックがわかったのではないでしょうか？

このように Hook は、自身がコンポーネントを新しいデータで **再描画する** 能力を持っています。

このコンポーネントを再描画させるという Hook の役割をしっかりと理解できていなかったので、  
React がチンプンカンプンだったんだなと記事にしてわかりました。

スッキリしました。



## 5.3.useState の更新関数の引数

先程見てきたソースコードはよろしくない部分があります。

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

export const Counter = () => {
  // useState フックを使ってクリックの回数をステート管理
  const [count, setCount] = useState<number>(0);

  return (
    <div>
      <p>{count} 回クリックしました。</p>
      <button onClick={() => setCount(count + 1)}>Click me</button>
    </div>
  );
}
```

それは、`setCount` の引数です。

何がいけないかと言いますと、

`setCount` の中で現在の state である `count` を参照して +1 をしています。  

:::note warn

連続でクリックしたときに、タイミングによっては `setCount` の更新が完了する前の `count` を参照してしまう場合があります。

:::

これを解決するために、`setCount` の引数には

```ts
setCount((prev) => prev + 1)
```

と関数を指定すると良いです。

こうすることで、  
更新する前の state の値が `prev` に渡され、その値に +1 をするため確実に更新することができます。

最終的なソースは以下の通りです。

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

export const Counter = () => {
  // useState フックを使ってクリックの回数をステート管理
  const [count, setCount] = useState<number>(0);

  return (
    <div>
      <p>{count} 回クリックしました。</p>
      <button onClick={() => setCount((prev) => prev + 1)}>Click me</button>
    </div>
  );
}
```


# 6.おわりに

分割代入と Hook の自身がコンポーネントを新しいデータで **再描画する** という内容を理解すると `useState` って難しくないんだなと感じました。

一つ一つの動きを確実に捉えていくことが大切ですね。

横着して、なんとなくの理解で進めてきていたため React って苦手意識を持ってしまっていたんだなと反省しました。

引き続き、Hook 関係の記事を挙げていきますので、見ていただけますと幸いです🙇‍♂️


併せて他の記事も読んでいただけると嬉しいです🙇‍♂️

https://qiita.com/daishiman/items/5acf803f252b82f970fe

https://qiita.com/daishiman/items/d382279a2a6cae3ea1aa

https://qiita.com/daishiman/items/e0d9e2e16382231f6200

https://qiita.com/daishiman/items/547b73aa3779b81cc329


最後まで読んでいただき、ありがとうございました😊

# 7.参考

- React ハンズオンラーニング web アプリケーション開発のベストプラクティス   
著: Alex Banks, Eve Porcello   
訳: 宮崎　空

- [【React Hooks】useStateの実用的な更新関数を作る](https://tech.playground.style/dev/react-usestate/)