useState

JS

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]); // 新しい配列を作って渡す
};