useState()とは
useStateとは状態(state)を管理するということ。
まずuseStateを使うには、
reactからuseStateという関数を呼び出すために以下を書きます。
import { useState } from "react";
useStateは配列を返却する関数で、状態(state)とstateの更新関数を分割代入で受け取ります。
const [num, setNum] = useState();
更新関数の名前はset+state名とつけます。
例えば、stateをnumにしたら、更新関数はsetNumになります。
初期値はuseState()のかっこの中に設定できます。
const [num, setNum] = useState(0);
ルール
useStateを使うには、関数コンポーネントの一番上に定義するのがルールです。
import { useState } from "react";
export const App = () => {
const [num, setNum] = useState(0);//一番上ここです。
const onClickClickCountUp = () => {
setNum((prev) => prev + 1);
};
return (
<>
<button onClick={onClickClickCountUp}>カウントアップ</button>
<p>{num}</p>
</>
);
};
setStateは非同期
setStateは非同期的に反映されます。下の例で、setCount(count + 1);を呼んでもすぐにcountは更新されません。
再レンダリングでcountを新しい値になります。
const [count, setCount] = useState(0);
const handleClick = () => {
setCount(count + 1);
console.log(count); // ここはまだ古い値
};
ステートがオブジェクトや配列の場合
ステートがオブジェクトや配列の場合、新しいオブジェクトをセットすることが重要です。
なぜなら
React は「前の状態と新しい状態を ===
(参照比較)で比較」して、変化があったかどうかを判断するからです。
ダメな例(オブジェクトの場合)
const [user, setUser] = useState({ name: "Taro", age: 20 });
const updateAge = () => {
user.age = 21; // ← オブジェクトを直接変更
setUser(user); // ← 同じオブジェクトを再セット
};
これは user === user
なので React は「変わってない」と判断し、再レンダリングしません。
正しい例(オブジェクトの場合)
const updateAge = () => {
setUser({ ...user, age: 21 }); // ← 新しいオブジェクトを生成して渡す
};
ダメな例(配列の場合)
const [items, setItems] = useState([1, 2, 3]);
const addItem = () => {
items.push(4); // 直接変更
setItems(items); // 同じ配列を再セット
};
正しい例(配列の場合)
const addItem = () => {
setItems([...items, 4]); // 新しい配列を作って渡す
};