React PR

【React入門】useStateが10分で理解できる!基本的な使い方5選

【React入門】useStateが10分で理解できる!基本的な使い方5選
記事内に商品プロモーションを含む場合があります

こんにちは!
useStateって聞いたことありますか?
今回は、Reactの重要な機能である「useState」について詳しく解説します。

useStateは、Reactで状態を管理するための強力なツールなんです。
でも「状態って何?」って思いましたか?
簡単に言えば、アプリの中で変化するデータのことです。
例えば、ボタンを押すたびに増える数字とか、ユーザーが入力したテキストとか。
そういったものを簡単に扱えるようにしてくれるのが、このuseStateなんです。

この記事でわかること
  • useStateの基本的な概念と使い方
  • 数値、文字列、真偽値など様々なデータ型での使用方法
  • useStateを使う際の注意点
  • 実際のアプリケーションでの活用例

React環境がない方はこちらも参考にしてください。

【たった1分】React×Vite×TypeScriptで高速ビルド環境を構築する方法
【たった1分】React×Vite×TypeScriptで高速ビルド環境を構築する方法こんにちは! 今日は、React、Vite(ヴィート)、TypeScriptを使用して、たった1分で高速にビルド環境を構築する方法につ...

useStateフックとは?

まずは、useStateフックの基本的な概念について説明しましょう。
useStateは、Reactの「フック」と呼ばれる機能の一つです。
フックとは、関数型コンポーネントで状態や他のReactの機能を使えるようにする特別な関数のこと。
その中でもuseStateは、コンポーネントに状態を追加するために使われます。

状態って何?と思う方もいるかもしれません。
簡単に言えば、アプリケーションの中で変化する可能性のあるデータのことです。
例えば、ユーザーの入力、APIからのデータ、時間の経過によって変わる値などが該当します。

useStateを使うと、この状態を簡単に管理できるんです。
値の更新と、その更新に伴う画面の再描画を自動的に行ってくれるので、開発者はロジックに集中できます。

以前のReactでは、クラスコンポーネントを使って状態を管理していました。
でも、useStateを含むフックの導入により、関数型コンポーネントでも簡単に状態管理ができるようになりました。
コードがシンプルになり、理解しやすくなったんです。

useStateは非常に柔軟で、数値、文字列、真偽値、オブジェクト、配列など、様々な型のデータを扱えます。

useStateの基本的な使い方

useStateの基本的な使い方を、5つの異なるデータ型を例に解説します。
それぞれのケースで、どのようにuseStateを使うのか、実際のコード例を交えて説明していきますね。

1. 数値の状態管理

まずは、最もシンプルな例として数値の状態管理を見てみましょう。
カウンターアプリを想像してください。
ボタンをクリックするたびに数字が増えていく、あのシンプルなアプリです。
このカウンターの数値を管理するのに、useStateが使えます。


import React, { useState } from 'react';

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

  const increment = () => {
    setCount(count + 1);
  };

  return (
    <div>
      <p>カウント: {count}</p>
      <button onClick={increment}>増やす</button>
    </div>
  );
};

このコードでは、useState(0)で初期値0の状態を作成しています。
countが現在の値、setCountが値を更新する関数です。
ボタンをクリックするとincrement関数が呼び出され、setCountで値が更新されます。

2. 文字列の状態管理

次は、文字列の状態管理です。
例えば、ユーザーの入力を管理する場合によく使われます。
入力フォームの値を状態として保持し、更新する例を見てみましょう。


import React, { useState } from 'react';

const InputForm = () => {
  const [name, setName] = useState<string>('');

  const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    setName(event.target.value);
  };

  return (
    <div>
      <input type="text" value={name} onChange={handleChange} />
      <p>こんにちは、{name}さん!</p>
    </div>
  );
};

ここでは、useState('')で空の文字列を初期値として状態を作成しています。
入力フォームの値が変更されるたびにhandleChange関数が呼び出され、setNameで状態が更新されます。

3. 真偽値の状態管理

真偽値(ブール値)の状態管理も、useStateでよく行われます。
例えば、何かの表示・非表示を切り替えるトグルスイッチなどに使えます。


import React, { useState } from 'react';

const ToggleSwitch = () => {
  const [isOn, setIsOn] = useState<boolean>(false);

  const toggle = () => {
    setIsOn(!isOn);
  };

  return (
    <div>
      <button onClick={toggle}>{isOn ? 'ON' : 'OFF'}</button>
      <p>{isOn ? '電気がついています' : '電気が消えています'}</p>
    </div>
  );
};

この例では、useState(false)で初期値がfalseの状態を作成しています。
ボタンをクリックするたびにtoggle関数が呼び出され、setIsOnで状態が反転します。

4. オブジェクトの状態管理

より複雑なデータ構造、例えばオブジェクトの状態管理もuseStateで行えます。
ユーザー情報のような複数のプロパティを持つデータを管理する場合に便利です。


import React, { useState } from 'react';

interface UserInfo {
  name: string;
  age: number;
}

const UserProfile = () => {
  const [user, setUser] = useState<UserInfo>({ name: '', age: 0 });

  const handleNameChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    setUser({ ...user, name: event.target.value });
  };

  const handleAgeChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    setUser({ ...user, age: Number(event.target.value) });
  };

  return (
    <div>
      <input type="text" value={user.name} onChange={handleNameChange} placeholder="名前" />
      <input type="number" value={user.age} onChange={handleAgeChange} placeholder="年齢" />
      <p>名前: {user.name}, 年齢: {user.age}</p>
    </div>
  );
};

この例では、名前と年齢を持つオブジェクトを状態として管理しています。
状態を更新する際は、setUserで新しいオブジェクトを作成して更新します。
オブジェクトの一部のプロパティだけを更新する場合は、スプレッド構文(...user)を使って他のプロパティを保持しつつ、特定のプロパティを更新しています。

5. 配列の状態管理

最後に、配列の状態管理を見てみましょう。
TODOリストのような、複数のアイテムを管理する場合によく使われます。


import React, { useState } from 'react';

const TodoList = () => {
  const [todos, setTodos] = useState<string[]>([]);
  const [newTodo, setNewTodo] = useState<string>('');

  const addTodo = () => {
    if (newTodo.trim() !== '') {
      setTodos([...todos, newTodo]);
      setNewTodo('');
    }
  };

  return (
    <div>
      <input
        type="text"
        value={newTodo}
        onChange={(e) => setNewTodo(e.target.value)}
        placeholder="新しいTODOを入力"
      />
      <button onClick={addTodo}>追加</button>
      <ul>
        {todos.map((todo, index) => (
          <li key={index}>{todo}</li>
        ))}
      </ul>
    </div>
  );
};

この例では、TODOアイテムの配列をuseStateで管理しています。
新しいTODOを追加する際は、setTodosで既存の配列に新しい要素を追加した新しい配列を作成しています。

useStateで複数の状態を管理するには

複数の状態を管理する方法はいくつかあります。
状況に応じて適切な方法を選びましょう。

複数のuseStateを使う

関連性の薄い複数の状態がある場合、それぞれに対してuseStateを使うのが簡単です。


const [name, setName] = useState<string>('');
const [age, setAge] = useState<number>(0);
const [isStudent, setIsStudent] = useState<boolean>(false);

オブジェクトとして管理

関連する複数の状態がある場合、一つのオブジェクトとして管理するのが便利です。


const [user, setUser] = useState<{ name: string; age: number; isStudent: boolean }>({
  name: '',
  age: 0,
  isStudent: false
});

更新時は、スプレッド構文を使って一部のプロパティだけを更新できます:


setUser(prevUser => ({ ...prevUser, name: 'Alice' }));

useReducerを使う

状態の更新ロジックが複雑な場合、useReducerフックを使うのも一つの選択肢です。
これについては、別途学習するのがおすすめですよ。

状態管理の方法は、アプリケーションの規模や複雑さによって変わってきます。
小規模なアプリケーションなら複数のuseStateで十分ですが、大規模になってくるとuseReducerReduxなどの状態管理ライブラリの使用を検討する必要があるかもしれません。

useStateと普通の変数の違いは?

useStateで管理される状態と普通の変数の主な違いは、状態が変更されたときの挙動です。

useStateで管理される状態が変更されると、Reactはそのコンポーネントを自動的に再描画します。
つまり、画面上の表示が新しい状態を反映して更新されるんです。

一方、普通の変数を変更しても、Reactはその変更を検知できません。
そのため、画面の更新は行われません。

例えば、カウンターアプリで普通の変数を使うと、こんな感じになります:


let count = 0;

const increment = () => {
  count += 1;
  console.log(count);  // 値は増えていますが、画面には反映されません
};

この場合、countの値は増えていきますが、画面上には反映されません。
useStateを使うことで、状態の変更と画面の更新を連動させられるんです。

useStateを使う際の注意点

useStateは便利な機能ですが、使う際にはいくつか注意点があります。
ここでは、主に2つの重要なポイントについて解説します。

状態更新の非同期性

まず知っておくべきなのは、useStateによる状態の更新は非同期的だということです。
これはどういうことでしょうか?
簡単に言えば、状態を更新する関数(setCountなど)を呼び出した直後に、その新しい値を使おうとしても、まだ更新が反映されていない可能性があるということです。

例えば、以下のようなコードは期待通りに動作しないかもしれません:


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

const incrementAndLog = () => {
  setCount(count + 1);
  console.log(count);  // この値は更新前の値かもしれません
};

このincrementAndLog関数では、setCountで値を更新した直後にconsole.logcountの値を出力していますが、この時点ではcountの値がまだ更新されていない可能性があります。

前の状態を基に更新する方法

このような問題を解決する方法の一つが、更新関数に関数を渡す方法です。
これを使うと、前の状態を確実に取得して、それを基に新しい状態を計算できます。


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

const incrementAndLog = () => {
  setCount(prevCount => {
    const newCount = prevCount + 1;
    console.log(newCount);  // この値は確実に更新後の値です
    return newCount;
  });
};

この方法を使えば、確実に最新の状態を基に更新できます。
特に、複数の更新を連続して行う場合や、現在の状態に依存して更新を行う場合に有効です。

また、オブジェクトや配列の状態を更新する際は、直接変更するのではなく、新しいオブジェクトや配列を作成して更新することが重要です。
これは、Reactが状態の変更を検知しやすくなり、不要な再描画を防ぐためです。


// オブジェクトの更新(正しい方法)
setUser(prevUser => ({ ...prevUser, name: 'Alice' }));

// 配列の更新(正しい方法)
setTodos(prevTodos => [...prevTodos, newTodo]);

これらの点に注意しながらuseStateを使うことで、より予測可能で効率的なReactアプリケーションが作れるようになります。

useStateの実践的な使用例

ここまでuseStateの基本的な使い方と注意点を学んできました。
では、実際のアプリケーションではどのように使われるのでしょうか?
ここでは、2つの実践的な例を通じて、useStateの活用方法を見ていきましょう。

シンプルなカウンターアプリ

まずは、シンプルなカウンターアプリを作ってみます。
このアプリでは、ボタンをクリックすると数字が増減するという基本的な機能を実装します。


import React, { useState } from 'react';

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

  const increment = () => {
    setCount(prevCount => prevCount + 1);
  };

  const decrement = () => {
    setCount(prevCount => prevCount - 1);
  };

  return (
    <div>
      <h2>カウンター</h2>
      <p>現在の数: {count}</p>
      <button onClick={increment}>増やす</button>
      <button onClick={decrement}>減らす</button>
    </div>
  );
};

export default Counter;

このカウンターアプリでは、useStateを使ってcountという状態を管理しています。
increment関数とdecrement関数で状態を更新し、その値を画面に表示しています。

注目すべき点は、状態を更新する際に前の状態を基に計算している点です。
これにより、複数の更新が連続して行われても正確に状態を管理できます。

TODOリストの作成

次に、もう少し複雑な例として、TODOリストを作ってみましょう。
このアプリでは、新しいTODOの追加、完了したTODOの削除、そして残りのTODO数の表示といった機能を実装します。


import React, { useState } from 'react';

interface Todo {
  id: number;
  text: string;
}

const TodoList = () => {
  const [todos, setTodos] = useState<Todo[]>([]);
  const [inputText, setInputText] = useState<string>('');

  const addTodo = () => {
    if (inputText.trim() !== '') {
      setTodos(prevTodos => [...prevTodos, { id: Date.now(), text: inputText }]);
      setInputText('');
    }
  };

  const deleteTodo = (id: number) => {
    setTodos(prevTodos => prevTodos.filter(todo => todo.id !== id));
  };

  return (
    <div>
      <h2>TODOリスト</h2>
      <input
        type="text"
        value={inputText}
        onChange={(e) => setInputText(e.target.value)}
        placeholder="新しいTODOを入力"
      />
      <button onClick={addTodo}>追加</button>
      <ul>
        {todos.map(todo => (
          <li key={todo.id}>
            {todo.text}
            <button onClick={() => deleteTodo(todo.id)}>完了</button>
          </li>
        ))}
      </ul>
      <p>残りのTODO: {todos.length}個</p>
    </div>
  );
};

export default TodoList;

この例では、2つの状態を管理しています。
todosはTODOリストの配列、inputTextは新しいTODOを入力するためのテキストです。

addTodo関数では、入力されたテキストを基に新しいTODOオブジェクトを作成し、既存のTODO配列に追加しています。
ここでも、前の状態を基に新しい配列を作成していますね。

deleteTodo関数では、指定されたIDのTODOを配列から削除しています。
filterメソッドを使って新しい配列を作成することで、元の配列を直接変更することを避けています。

また、残りのTODO数を表示する部分では、todos.lengthを使って簡単に計算しています。
これはtodosの状態が変わるたびに自動的に更新されます。

これらの例を通じて、useStateがどのように実際のアプリケーションで使われるのかがわかったのではないでしょうか。
シンプルな状態管理から、より複雑なデータ構造の管理まで、useStateは幅広く活用できます。

キャリア形成/給与還元
ひとつひとつ真摯に向き合う企業
ONE_WEDGE社員募集

株式会社 ONE WEDGEでは、新たな仲間を募集しています!

私たちと一緒に、革新的で充実したキャリアを築きませんか?
当社は、従業員が仕事と私生活のバランスを大切にできるよう、充実した福利厚生を整えています。

  • 完全週休2日制(土日休み)で、祝日や夏季休暇、年末年始休暇もしっかり保証!
  • 様々な休暇制度(有給、慶弔、産前・産後、育児、バースデー休暇)を完備!
  • 従業員の成長と健康を支援するための表彰制度、資格取得支援、健康促進手当など!
  • 生活を支えるテレワーク手当、記事寄稿手当、結婚祝金・出産祝金など、様々な手当を提供!
  • 自己啓発としての書籍購入制度や、メンバー間のコミュニケーションを深める交流費補助!
  • 成果に応じた決算賞与や、リファラル採用手当、AI手当など、頑張りをしっかり評価!
  • ワークライフバランスを重視し、副業もOK!

株式会社 ONE WEDGEでは、一人ひとりの従業員が自己実現できる環境を大切にしています。
共に成長し、刺激を与え合える仲間をお待ちしております。
あなたの能力と熱意を、ぜひ当社で発揮してください。
ご応募お待ちしております!

ホームページ、採用情報は下記ボタンからご確認ください!

応募、ご質問など、LINEでお気軽にご相談ください♪

まとめ

ここまで、ReactのuseStateフックについて詳しく見てきました。
改めて、重要なポイントを振り返ってみましょう。

  • useStateは、関数コンポーネントで状態を管理するためのフックです。
  • 様々なデータ型(数値、文字列、真偽値、オブジェクト、配列など)で使用できます。
  • const [state, setState] = useState(initialValue)の形で使います。
    stateが現在の状態、setStateが状態を更新する関数です。
  • 状態の更新は非同期的に行われます。
    更新直後に新しい値を使用したい場合は注意が必要です。
  • 前の状態を基に更新する場合は、更新関数に関数を渡すのが安全です。
    例:setCount(prevCount => prevCount + 1)
  • オブジェクトや配列の状態を更新する際は、新しいオブジェクトや配列を作成して更新します。
  • useStateを使うことで、動的で対話的なユーザーインターフェースを簡単に作成できます。

useStateは、Reactアプリケーション開発の基本的なツールの一つです。
これをマスターすることで、より複雑な状態管理や他のReactフックの理解へとステップアップできます。

次のステップとしては、useEffectフックを学ぶのがおすすめです。
useEffectを使うことで、副作用(サイドエフェクト)の管理ができるようになり、より高度なアプリケーションの開発が可能になります。

また、状態管理がより複雑になってきたら、useReducerフックやReduxのような状態管理ライブラリの使用も検討してみてください。

COMMENT

メールアドレスが公開されることはありません。 が付いている欄は必須項目です