ReactのuseState入門 — 画面の状態を管理する
はじめに
Reactで「ボタンを押したらカウントが増える」「入力フォームの値を保持する」といった動きを実現するには State(状態) の管理が必要です。
関数コンポーネントでStateを扱うフックが useState です。
useStateの基本
import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0); // 初期値は0
return (
<div>
<p>{count}</p>
<button onClick={() => setCount(count + 1)}>+1</button>
</div>
);
}
useState は配列を返します。
const [状態の値, 更新関数] = useState(初期値);
-
count:現在の値(読み取り専用) -
setCount:値を更新する関数 -
0:初期値
なぜ普通の変数ではダメなのか
// NG: これでは画面が更新されない
function Counter() {
let count = 0;
return (
<div>
<p>{count}</p>
<button onClick={() => { count++; }}>+1</button>
</div>
);
}
Reactは「Stateが変化した時」だけ再描画します。普通の変数を変えても再描画が走らないため、画面に反映されません。
setCount を呼ぶ → Reactが再描画を検知 → 画面が更新される という流れが重要です。
Stateの更新は直接変更ではなく置き換え
// NG: Stateを直接変更する(再描画されない)
count = count + 1;
// OK: setXxx()で新しい値を渡す
setCount(count + 1);
オブジェクトや配列の場合も同様です。
const [user, setUser] = useState({ name: '田中', age: 25 });
// NG: プロパティを直接変更
user.age = 26;
// OK: スプレッド演算子で新しいオブジェクトを作る
setUser({ ...user, age: 26 });
const [list, setList] = useState([1, 2, 3]);
// NG: pushで直接追加
list.push(4);
// OK: 新しい配列を作って渡す
setList([...list, 4]);
前の値を使って更新する
ボタンを連続クリックするような場合、前の値に依存して更新する時は関数形式を使います。
// 関数形式(推奨)
setCount(prev => prev + 1);
// 値形式(非推奨:連続更新で問題が起きることがある)
setCount(count + 1);
複数のStateを持つ
function Form() {
const [name, setName] = useState('');
const [age, setAge] = useState(0);
const [isAdmin, setIsAdmin] = useState(false);
return (
<form>
<input value={name} onChange={e => setName(e.target.value)} />
<input type="number" value={age} onChange={e => setAge(Number(e.target.value))} />
<input type="checkbox" checked={isAdmin} onChange={e => setIsAdmin(e.target.checked)} />
</form>
);
}
関連するStateはオブジェクトにまとめることもできます。
const [form, setForm] = useState({ name: '', age: 0 });
// 特定のフィールドだけ更新
setForm(prev => ({ ...prev, name: '田中' }));
Javaエンジニアがつまずくポイントまとめ
| よくあるミス | 正しい書き方 |
|---|---|
count++ で更新 |
setCount(count + 1) |
user.age = 26 で更新 |
setUser({ ...user, age: 26 }) |
list.push(item) で追加 |
setList([...list, item]) |
| 値形式で連続更新 | 関数形式 prev => prev + 1 を使う |
まとめ
-
useStateでStateを宣言し、setXxxで更新する - Stateを更新すると自動で再描画される
- Stateは直接変更せず、常に新しい値/オブジェクトを渡す
- 前の値に依存する更新は関数形式
prev => ...を使う
次回は useEffect で副作用処理(データ取得・タイマーなど)の扱い方を整理します。