← ホームに戻る

React Hooks - useState

useStateで状態管理を学ぼう

useState - 状態管理の基礎

Reactで「変化する値」を扱うには、useStateを使います。


状態(State)とは?

状態とは、「時間とともに変化する値」のことです。

例:

  • カウンター(クリックするたびに増える数値)
  • 入力フォームの値
  • モーダルの開閉状態
  • チェックボックスのON/OFF

なぜuseStateが必要?

通常の変数では、Reactは再レンダリングしてくれません。

❌ 通常の変数(動かない)

function Counter() { let count = 0; // 通常の変数 const increment = () => { count = count + 1; console.log(count); // コンソールには表示されるが... }; return ( <div> <p>カウント: {count}</p> {/* 画面は更新されない! */} <button onClick={increment}>増やす</button> </div> ); }

✅ useState(動く)

import { useState } from 'react'; function Counter() { const [count, setCount] = useState(0); // useState を使う const increment = () => { setCount(count + 1); // setCount で更新 }; return ( <div> <p>カウント: {count}</p> {/* 画面が更新される! */} <button onClick={increment}>増やす</button> </div> ); }

useStateの基本

書き方

const [状態変数, 更新関数] = useState(初期値);
  • 状態変数: 現在の値を格納
  • 更新関数: 値を更新するための関数
  • 初期値: 最初の値

具体例

import { useState } from 'react'; function Example() { // countという状態を作る、初期値は0 const [count, setCount] = useState(0); return ( <div> <p>現在の値: {count}</p> <button onClick={() => setCount(count + 1)}> 増やす </button> </div> ); }

いろいろな型の状態

文字列の状態

function NameInput() { const [name, setName] = useState(""); return ( <div> <input type="text" value={name} onChange={(e) => setName(e.target.value)} /> <p>入力された名前: {name}</p> </div> ); }

真偽値の状態

function ToggleButton() { const [isOn, setIsOn] = useState(false); return ( <div> <p>状態: {isOn ? "ON" : "OFF"}</p> <button onClick={() => setIsOn(!isOn)}> 切り替え </button> </div> ); }

オブジェクトの状態

interface User { name: string; age: number; } function UserForm() { const [user, setUser] = useState<User>({ name: "", age: 0 }); return ( <div> <input type="text" placeholder="名前" value={user.name} onChange={(e) => setUser({ ...user, name: e.target.value })} /> <input type="number" placeholder="年齢" value={user.age} onChange={(e) => setUser({ ...user, age: Number(e.target.value) })} /> <p>名前: {user.name}, 年齢: {user.age}</p> </div> ); }

重要: オブジェクトを更新する時は、スプレッド構文(...user)を使って、他のプロパティを保持します。

配列の状態

function TodoList() { const [todos, setTodos] = useState<string[]>([]); const [input, setInput] = useState(""); const addTodo = () => { setTodos([...todos, input]); // 新しい配列を作る setInput(""); // 入力欄をクリア }; return ( <div> <input value={input} onChange={(e) => setInput(e.target.value)} /> <button onClick={addTodo}>追加</button> <ul> {todos.map((todo, index) => ( <li key={index}>{todo}</li> ))} </ul> </div> ); }

複数のuseStateを使う

1つのコンポーネントで、複数の状態を管理できます。

function LoginForm() { const [email, setEmail] = useState(""); const [password, setPassword] = useState(""); const [rememberMe, setRememberMe] = useState(false); const handleSubmit = () => { console.log({ email, password, rememberMe }); }; return ( <div> <input type="email" value={email} onChange={(e) => setEmail(e.target.value)} placeholder="メールアドレス" /> <input type="password" value={password} onChange={(e) => setPassword(e.target.value)} placeholder="パスワード" /> <label> <input type="checkbox" checked={rememberMe} onChange={(e) => setRememberMe(e.target.checked)} /> ログイン状態を保持 </label> <button onClick={handleSubmit}>ログイン</button> </div> ); }

よくある間違い

❌ 直接状態を変更しない

const [user, setUser] = useState({ name: "太郎", age: 25 }); // ダメな例 user.name = "花子"; // 直接変更してはダメ! // 正しい例 setUser({ ...user, name: "花子" });

❌ 更新関数を呼ばずに値を代入しない

const [count, setCount] = useState(0); // ダメな例 count = 5; // 直接代入してはダメ! // 正しい例 setCount(5);

前の状態に基づいて更新する

連続して状態を更新する場合は、関数形式を使います。

問題のある例

const [count, setCount] = useState(0); const incrementThreeTimes = () => { setCount(count + 1); setCount(count + 1); setCount(count + 1); // 期待: 3増える // 実際: 1しか増えない! };

正しい例

const [count, setCount] = useState(0); const incrementThreeTimes = () => { setCount(prev => prev + 1); setCount(prev => prev + 1); setCount(prev => prev + 1); // 期待通り3増える! };

実践例:簡単なカウンターアプリ

import { useState } from 'react'; function Counter() { const [count, setCount] = useState(0); return ( <div style={{ textAlign: 'center', padding: '20px' }}> <h1>カウンター</h1> <p style={{ fontSize: '48px', fontWeight: 'bold' }}> {count} </p> <div> <button onClick={() => setCount(count - 1)}>-1</button> <button onClick={() => setCount(0)}>リセット</button> <button onClick={() => setCount(count + 1)}>+1</button> </div> </div> ); } export default Counter;

まとめ

  • useState: 状態(変化する値)を管理するHook
  • 書き方: const [状態, 更新関数] = useState(初期値)
  • 更新方法: 更新関数を使う(直接代入しない)
  • 複数の状態: 複数のuseStateを使える
  • オブジェクト/配列: スプレッド構文で更新
  • 関数形式: 前の状態に基づいて更新する時に使う

次は、副作用を扱うuseEffectを学びましょう!