const [state, setState] = useState<S>(initialState)
// 型推論が効く場合
const [count, setCount] = useState(0); // number
const [name, setName] = useState(''); // string
// 明示的に型指定
const [user, setUser] = useState<User | null>(null);import { useState } from 'react';
// ── 数値の state(最もシンプルな例)──────────────────
function Counter() {
// useState(0) → 初期値0のカウンター
// count: 現在の値、setCount: 値を変更する関数
const [count, setCount] = useState(0);
return (
<div>
<p>カウント: {count}</p>
{/* setCount に新しい値を直接渡す */}
<button onClick={() => setCount(count + 1)}>+1</button>
{/* 関数型更新: 前の値(prev)を使って確実に計算 */}
<button onClick={() => setCount(prev => prev - 1)}>-1</button>
{/* 0 に戻す */}
<button onClick={() => setCount(0)}>リセット</button>
</div>
);
}
// ── 文字列の state(入力フォーム)──────────────────
function NameInput() {
const [name, setName] = useState(''); // 初期値は空文字
return (
<div>
{/* input の値を state と同期させる(Controlled Component)*/}
<input
value={name}
onChange={e => setName(e.target.value)} // 入力のたびに更新
placeholder="名前を入力..."
/>
<p>こんにちは、{name || 'ゲスト'}さん!</p>
</div>
);
}
// ── オブジェクトの state ─────────────────────────────
function ProfileForm() {
const [profile, setProfile] = useState({ name: '', age: 0 });
const updateName = (name: string) => {
// ⚠️ オブジェクトは必ずスプレッド構文でコピーしてから更新
setProfile(prev => ({ ...prev, name }));
};
return <input value={profile.name} onChange={e => updateName(e.target.value)} />;
}初期値に計算コストの高い処理を渡す場合は、関数形式 useState(() => expensiveCalc()) を使うと初回レンダー時のみ実行される。
useState は「コンポーネントが覚えておく値」を管理するフック。ボタンのクリック回数やフォームの入力値などを保持し、値が変わると自動で画面が更新される(再レンダー)。技術的には第1引数に初期値を渡すと[現在の状態, 更新関数]を返します。setState()を呼ぶとコンポーネントが再レンダーされます。オブジェクト・配列を状態にするときは、必ずスプレッド構文などで新しい参照を作って渡します(ミューテーションは検知されません)。重い計算の初期化には遅延初期化(()=> expensiveCalc())を使うと初回だけ実行されます。