useState — Reactの状態管理の始まり
このトピックを終えると
useStateを使って状態を作成および更新する方法、そしてリレンダーが発生する仕組みを理解できるようになります。
通常の変数ではダメ
javascript
function Counter() {
let count = 0;
function handleClick() {
count += 1;
console.log(count); // 1, 2, 3... と増えていく
}
return <button onClick={handleClick}>{count}</button>;
// 画面には常に 0
}countは増えていくものの、画面は変わりません。Reactは通常の変数の変更を検知できません。画面を更新するには、Reactに「状態が変化した」と知らせる必要があります。
useState
javascript
import { useState } from "react";
function Counter() {
const [count, setCount] = useState(0);
return (
<button onClick={() => setCount(count + 1)}>
{count}
</button>
);
}useState(0)は、次の2つを返します。
count: 現在の状態の値setCount: 状態を変更する関数
setCountを呼び出すと、Reactはコンポーネントをリレンダーします。新しいcountの値で画面が再描画されます。
状態の更新は非同期です
javascript
function handleClick() {
setCount(count + 1);
console.log(count); // まだ以前の値!
}setCountを呼び出しても、countがすぐに変わりません。次のレンダーで新しい値が反映されます。
以前の値を基に更新する場合は、関数形式の更新を使用します。
javascript
setCount(prev => prev + 1);prevには、現在の最新の値が格納されます。連続して複数回呼び出しても正確です。
javascript
setCount(prev => prev + 1);
setCount(prev => prev + 1);
setCount(prev => prev + 1);
// count が 3 増加オブジェクトと配列の状態
javascript
const [user, setUser] = useState({ name: "Alice", age: 25 });
// 悪い例:直接修正
user.age = 26; // React が変更を検知できない
setUser(user); // 同じ参照なのでリレンダーされない
// 良い例:新しいオブジェクトを作成
setUser({ ...user, age: 26 });Reactは、参照が変わったかどうかを確認します。既存のオブジェクトを修正すると、参照が同じになるため、変更を検知できません。スプレッド演算子を使って新しいオブジェクトを作成する必要があります。
配列も同様です。
javascript
const [items, setItems] = useState(["a", "b"]);
// 追加
setItems([...items, "c"]);
// 削除
setItems(items.filter(item => item !== "b"));
// 修正
setItems(items.map(item => item === "a" ? "A" : item));push、spliceのような元の値を変更するメソッドは使用しません。
複数の useState
javascript
const [name, setName] = useState("");
const [age, setAge] = useState(0);
const [isActive, setIsActive] = useState(false);関連のない状態は別々に宣言します。常に一緒に変わる値は、1つのオブジェクトにまとめることもできます。
重要なポイント
useStateは、Reactコンポーネントに状態を追加し、setStateの呼び出し時にリレンダーを行います。 状態の更新は非同期であるため、以前の値に基づいて更新する場合は、関数形式(prev => ...)を使用してください。 オブジェクト/配列の状態は、元の値を変更せずに新しいものを作成する必要があります。