LoginSignup
28
32

More than 1 year has passed since last update.

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

Last updated at Posted at 2022-10-18

1.はじめに

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

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

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

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

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

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

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

2.目次

1.はじめに
2.目次
3.この記事でわかること
4.環境
5.useState とは
 5.1.state とは? Hookとは?
 5.2.useState とは
 5.3.useState の更新関数の引数
6.おわりに
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 の説明に入る前に、stateHook とは何かについて振れておきます。

state とは、

  • コンポーネント(再利用できる部品)の描画(ブラウザに表示)後に変更する値のこと

Hook とは、

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

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

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

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

5.2.useState とは

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

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

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 はこのように配列の分割代入を用いて記述します。

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

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

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

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

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

useState は、この部分ですね。

まずは、useState<number>(0) ですが、

  • state の引数は number 型
  • state の初期値は 0

という意味になります。

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

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

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

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

// この 0 は 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 値を更新する関数コンポーネントを再描画させる 役割

となっています

今までの内容をまとめると、

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

ということになります。

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

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 + 1count に代入され count を更新する
  6. 以降 2 ~ 5 を繰り返す

useState修正.png

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

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

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

スッキリしました。

5.3.useState の更新関数の引数

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

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 をしています。

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

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

setCount((prev) => prev + 1)

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

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

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

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 関係の記事を挙げていきますので、見ていただけますと幸いです🙇‍♂️

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

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

7.参考

28
32
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
28
32