ReactのuseStateを解説

React_icon React
この記事は約10分で読めます。

この記事は、以下の方を対象に書いています。

  • useStateの基本的な使い方を知りたい
  • useStateを使ったサンプルコードを見たい
  • TypeScriptと合わせたサンプルコードが見たい

useStateの宣言

useStateは、Reactフックの1つで、状態を管理するためのものです。

いきなりだと分かりづらいと思いますので、サンプルコードを見て理解を深めていきましょう。

まず、宣言するための構文は下記の通りです。

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

count … 変数なのでプログラマーが自由に決めて良い。

setCount … 「set」を先頭につけて、変数の先頭を大文字にする。

<number> … TypeScriptの型注釈。ユニオン型やインターフェイスでも可。

(0) … 初期値を設定。型を指定している場合は、その型に合っていないとエラー。

基本的な使い方

ここでは、useStateの基本的な使い方を紹介します。

まずは、基本型(numberやstring)のuseStateの使い方です。

サンプルコード①

ボタンを押すと、カウントアップ(+1)されるプログラムを作成してみます。

また、リセットボタンを押すと1に戻るようにしてみます。

import React, { useState } from 'react';
import './App.css';

function App() {
  // useStateの宣言と初期化(1)
  const [count, setCount] = useState<number>(1);

  // 「Click Me!」ボタンが押された時の処理
  const countUp = (): void => {
    // setter(現在の状態に+1)
    setCount(count + 1);
  };

  // 「Click Me!」ボタンが押された時の処理
  const resetCount = (): void => {
    // setter(1に変更)
    setCount(1)
  };

  return (
    <div className="App">
      {/* 調整用 */}
      <div style={{ height: '10px' }}></div>

      {/* 現在のcount */}
      <div>{count}</div>

      {/* 調整用 */}
      <div style={{ height: '10px' }}></div>

      <div>
        {/* カウントアップボタン */}
        <button onClick={countUp}>Click Me!</button>
      </div>

      <div>
        {/* リセットボタン */}
        <button onClick={resetCount}>Reset Me!</button>
      </div>
    </div>
  );
}

export default App;

上記のプログラムでは、カウントアップのための数字を管理するためにuseStateが必要になります。

そして、そのuseStateはボタンのアクションによって、セッターを用いて状態の更新を行います。

こうして、必要な部分のみが再描画(再レンダリング)され、数字が変化します。

ちなみに、カウントアップ後に画面更新をすると、初期値へ戻ります。

サンプルコード②

次は、入力された文字を大文字に変換して表示するプログラムを作成してみます。

import React, { useState } from 'react';
import './App.css';

function App() {
  // useStateの宣言と初期化(空白)
  const [text, setText] = useState<string>('');

  // テキストボックスに変化があった際に呼び出される
  const formattedText = (e: any): void => {
    // 入力値をstring型として再定義
    const newText: string = e.target.value as string
    // 入力値がstring型じゃなければ、暗黙的なundefinedを返却
    if (typeof newText !== 'string') {
      return
    }
    // setter(newTextがnullやundefinedじゃなければ、大文字に変換した値を返却、それ以外は空文字)
    setText(newText ? newText.toUpperCase() : '')
  };

  return (
    <div className="App">
      {/* テキストボックス(変化があった場合にformattedText関数を呼び出す) */}
      <div>
        <input type="text" value={text} onChange={(e: any): void => formattedText(e)} />
      </div>

      {/* useStateの現在の値を描画 */}
      <div>
        {text}
      </div>

    </div>
  );
}

export default App;

今回は、string型のuseStateを使ってみました。

string型でも変わらず、setterを用いて状態の更新をして、値を再描画します。

応用的な使い方

次に応用的な使い方を紹介します。

useStateは、基本型だけではなくオブジェクトの状態管理も可能です。

サンプルコード①

今回は、オブジェクトをuseStateに格納して状態管理をしてみます。

オブジェクトの作成に関しては、以下の記事でも紹介していますのでご参考に。

import { useState } from "react";

const App = () => {
  // objectを格納したuseStateを準備(各要素は空文字)
  const [form, setForm] = useState({ firstName: '', lastName: '' });

  // テキストボックスの内容に変化があった場合に呼び出される
  const updateForm = (e: { target: { name: any; value: any; }; }) => {
    setForm({
      // スプレット構文を用いてオブジェクトのコピー
      ...form,
      // 値の上書き
      // 以下の文だと再描画はされない
      // form[e.target.name] = e.target.value;
      [e.target.name]: e.target.value
    });
  };

  return (
    <div>
      {/* テキストボックス(変更があった場合にupdateFormを呼び出す) */}
      <div>
        <input name="firstName" value={form.firstName} onChange={updateForm} />
      </div>
      {/* テキストボックス(変更があった場合にupdateFormを呼び出す) */}
      <div>
        <input name="lastName" value={form.lastName} onChange={updateForm} />
      </div>

      {/* 現在の値を描画 */}
      <div>{`first name: ${form.firstName}`}</div>
      <div>{`last name: ${form.lastName}`}</div>
    </div>
  );
};
export default App;

上記のコードのコメントにも記載しましたが、重要なことですので再度書いておきます。

useStateでオブジェクトの状態変更をする際は、オブジェクトが同一だと見なされれば、

再描画(レンダリング)は行われませんので、注意が必要です。

サンプルコード②

次は、配列の状態管理を行い、要素を追加したり、削除したりできるサンプルコードを紹介します。

import { useState } from "react";

const App = () => {
  // string型の配列を定義(初期値は空の配列)
  const [items, setItems] = useState<string[]>([]);

  // Add Itemボタンを押下した際に呼び出される
  const addItem = (item: string) => {
    // スプレット構文を使用し、コピーした配列に新しい要素を追加
    setItems([...items, item]);
  };

  // Removeボタンを押下した際に呼び出される
  const removeItem = (index: number) => {
    // すでにある配列の中から、index番目のRemoveボタンを探し出しtrueを返すものを除外してitemsにセット
    setItems(items.filter((_, i) => i !== index));
  };

  return (
    <div>
      {/* 追加用ボタン、クリックするとaddItem関数を呼び出し */}
      <button onClick={() => addItem('New Item')}>Add Item</button>

      {/* itemsの要素数分ループ */}
      {items.map((item, index) => (
        // ループさせてHTML要素を作成する場合はkeyを設定
        <div key={`item-${index}`}>
          {/* itemsの要素を描画 */}
          {item}
          {/* Removeボタンを作成、クリックするとremoveItem関数を呼び出し */}
          <button onClick={() => removeItem(index)}>Remove</button>
        </div>
      ))}
    </div>
  );
};
export default App;

今回も、useStateが更新され描画がうまくできるように、スプレット構文を使用しています。

まとめ

useStateは、Reactが持つhooksの一つです。

useStateは、状態管理をするもので、setterを使って状態の変更を制御します。

TypeScriptと組み合わせることで、より強力でバグに強いプログラムが完成します。

他のhooksとうまく組み合わせて使うことで更に便利になります。

コメント

タイトルとURLをコピーしました