Lesson 4

コンポーネント内のStateを管理する

Lesson 4 Chapter 1
State

Lesson3ではReactの基礎文法として、JSX記法、イベント処理、Props、ルーティング等を学びました。これらは今後何度も登場するので、自信のない方は復習しておきましょう。本レッスンではReactにおける最重要概念の一つであるStateについて学習していきます。

Stateとは

コンポーネントの状態を値としてもつ変数をStateといいます。コンポーネントで必要に応じてStateを定義し、特定のイベントで更新してやることで、動的なアプリケーションを作成することが可能となります。コンポーネントの状態の具体例として以下のようなものがあげられます。

  • ボタンを押すことでカウントアップしていく値
  • ボタンのON/OFFの状態
  • テキストボックスの入力

他にも様々な状態をStateとして保有することができます。具体的にStateを使用した例を見たほうが理解しやすいと思うので、いくつか紹介します。以下の2つの画像は押す度に表示のONとOFFが切り替わるボタンの例です。上の画像がOFFの時、下の画像がONの時になります。

2023-02-28-09-32-45_.png 青色の背景に"OFF"と表示されています。

2023-02-28-09-32-58_.png 赤色の背景に"ON"と表示されています。

文字だけでなく背景色も連動して変わっています。ここでは、コンポーネントのStateとしてボタンのON/OFFの状態を定義しています。以下の2つの画像はc1とc2のテキストボックスに数値を入力し、"計算"のボタンをクリックすると、入力値の四則演算の結果を表示する例です。

2023-02-28-11-10-54_.png 足し算、引き算、掛け算の結果が0、割り算の結果が非表示になっています(初期表示)。

2023-02-28-11-11-29_.png c1=10、c2=5の四則演算の結果が表示されています。

ここでは、コンポーネントのStateとしてc1とc2の入力値および四則演算の計算結果を定義しています。もう一例見てみましょう。以下の4つの画像はテキストボックスに文字を入力し、"追加"のボタンをクリックすると、入力したテキストを表示に追加する例です。

2023-02-28-11-47-14_.png テキストボックスと"追加"のボタンが表示されています(初期表示)。

2023-02-28-11-47-28_.png テキストボックスと"りんご"と入力されています。

2023-02-28-11-47-43_.png "追加"のボタンをクリックすると、"りんご"と表示されます。

2023-02-28-11-48-21_.png テキストボックスにテキストを入力し"追加"のボタンをクリックする度に、入力したテキストが追加されていきます。

ここでは、コンポーネントのStateとしてテキストボックスに入力されたテキストと追加されたテキストの一覧を定義しています。簡単な例ですが、以上のようなことがStateを使用することで実現できます。

StateとPropsの違い

ところでレッスン3でStateと似た概念としてPropsを学びました。混同しないようにこれらの違いを確認してみます。ReactでStateとPropsはそれぞれ以下を意味します。

  • State: コンポーネントが持っている状態
  • Props: 親コンポーネントから子コンポーネントへ渡されるデータ

性質としては以下のような違いがあります。

  • State: 値の更新が可能
  • Props: 親コンポーネントで値を代入した後の更新が不可能

直感的には以下のようなイメージになります。

StateProps.png 親コンポーネントから子コンポーネントへPropsがデータを運んでいます。

Stateはコンポーネントが生成する状態であり、Propsは親コンポーネントから子コンポーネントへのStateや変数を積み荷として受け渡す船のようにイメージすると分かりやすいかと思います。

Lesson 4 Chapter 2
useStateを使ってState管理する

useStateの配列の中身

先ほどは概念的にStateの説明しました。ここからは実際にStateの定義の仕方や管理方法を学習していきます。StateおよびStateを更新する関数を定義する関数として、useStateがReactの機能として提供されています。useStateを使用するときはファイルの先頭でReactからimportする必要があります。useStateの使用方法は以下のようになります。

const [num, setNum] = useState();

useStateは配列を返します。配列の最初の要素がStateであり、2番目の要素がStateを更新する関数になります。上記においてはnumがStateになり、setNumがStateを更新する関数になります。Stateの名前は自由に命名できるので使用目的に応じた名前にしましょう。またStateを更新する関数は"setNum"のようにStateの名前の前に"set"を付けてキャメルケースで命名するのが暗黙のルールとなっていますので特別な理由がなければルールに従うようにしましょう。Stateの更新はStateを更新する関数が実行されるときに、引数として与えられた値に上書きされます。例えば

setNum(0);

が実行された後、numは0に更新されます。現在のStateの値を参照して更新する場合、

setNum(num+1);

のように記述します。更新前にnumが9であった場合、上記の更新により10になります。数値ばかりでなく、文字列、真偽値、配列、オブジェクト等、他のJavaScriptの変数もStateで管理することができます。

初期値の設定

先ほど示した方法でuseStateを使用すると、Stateの初期値はundefinedになります。Stateに初期値を設定したい場合、useStateに引数を与えることで与えた引数をStateの初期値に設定できます。例えば、

const [num, setNum] = useState(0);

とすると数値の0が、

const [num, setNum] = useState(false);

とするとfalseが、

const [num, setNum] = useState("こんにちは!");

とすると"こんにちは!"がnumの初期値に設定されます。useStateの使用方法についての説明は以上になりますが最後にuseStateの使用において注意すべき点を説明します。useStateを記述できるのは関数コンポーネントのトップレベルのみです。そのため、コンポーネント内で定義している関数の中はもちろん、if文やfor文の中でも使用することができません。使用できる場所とできない場所の例を以下に示すので参考にしてください。

import { useState } from "react";

// ここではuseStateが使えません。
                      
const Test = () =>{
                      
// ここではuseStateが使えます。
                      
  const onClickButton = () => {
      // ここではuseStateが使えません。
  }
                      
  if (true) {
      // ここではuseStateが使えません。
  }
                      
                      
  // ここではuseStateが使えます。
                      
  return (
      <>
        <p>{num}</p>
        <button onClick={onClickButton} >ボタン</button>
      </>    
  ) ;
                      
// ここではuseStateが使えません(エラーにはならないが機能しません)。
                              
}
                      
// ここではuseStateが使えません。
                      
export {Test}

カウントアップ機能の実装

ここまではStateの概念、定義および更新方法について説明してきました。ここからはカウントアップ機能の実装を通して、Stateの活用方法を学習しましょう。カウント、カウントアップするボタンおよびカウントをクリアするボタンを表示するコンポーネントCountUp.jsxを作成します。以下に習って作成し、Componentsフォルダに保存しましょう。

CountUp.jsx
import { useState } from "react"
const CountUp = () => {

  const [num, setNum] = useState(0);
                    
  const onClickButtonForCountUp = () => {
    setNum(num+1);
  }
                    
  const onClickButtonForClear = () => {
    setNum(0);
  }
                    
  return (
    <>
      <p>{num}</p>
      <button onClick={onClickButtonForCountUp} >count up</button>
      <button onClick={onClickButtonForClear} >clear</button>
    </>                                
  );
                    
}
                    
export {CountUp};

CountUp.jsxの内容を確認していきましょう。CountUp関数を上から確認していくと、最初にuseStateを使用してnumというStateとsetNumというState更新用の関数を定義しています。ここで定義したnumがカウントを保持するStateになります。初期値は0に設定されています。その次にonClickButtonForCountUp関数が定義されています。onClickButtonForCountUp関数は、内容が"setNum(num+1)"であることから、numに1追加する関数であることが分かります。その次に定義されているonClickButtonForClear関数は、内容が"setNum(0)"であることから、numを0で上書きする関数であることが分かります。return文を見てみるとnumを表示する文、onClickButtonForCountUp関数を実行する”count up”ボタン、そしてonClickButtonForClear関数を実行する”clear”ボタンのJSXが記述されているのが確認できます。srcフォルダにあるApp.jsxにCountUpコンポーネントをimportして表示させてみましょう。App.jsxを以下のように編集します。

App.jsx
import { CountUp } from "./components/CountUp"

const App = () => {
                      
  return(
    <CountUp />
  );
                      
}
                      
export {App};

作成出来たらブラウザで表示を確認しましょう。以下のように表示されるはずです。

2023-02-22-21-17-21_.png 0のカウントの表示、"count up"ボタンおよび"clear"ボタンが表示されてます。

0のカウントの値、"count up"ボタン、"clear"ボタンが表示されています。"count up"ボタンをクリックすると、表示されてるカウントが1ずつ増加していくことが確認できると思います。以下は5回"count up"をクリックしたときの表示です。

2023-02-22-21-18-21_.png カウントの表示が5になっています。

表示されてるカウントが5になることが確認できると思います。以下は"clear"ボタンをクリックしたときの表示です。

2023-02-22-21-20-48_.png カウントの表示が0になりました。

表示されてるカウントが0になることが確認できると思います。このようにStateを使いこなせるようになると、UI作成の自由度が格段に向上します。今後のレッスンを通じて徐々に使いこなせるようにしていきましょう。