ReactのuseState入門:基本から配列・オブジェクトの更新まで

スポンサーリンク

ReactのuseState入門:基本から配列・オブジェクトの更新まで

useStateとは

useState はReactコンポーネントに状態を持たせるためのフックです。状態が変わるとコンポーネントが再レンダリングされます。


基本的な使い方

import { useState } from 'react'

function Counter() {
  const [count, setCount] = useState(0)

  return (
    <div>
      <p>{count}</p>
      <button onClick={() => setCount(count + 1)}>+1</button>
    </div>
  )
}

useState(初期値)[現在の値, 更新関数] のタプルを返します。


TypeScriptで型を指定する

初期値から型推論されますが、明示的に指定することもできます。

const [count, setCount] = useState<number>(0)
const [name, setName] = useState<string>('')
const [isOpen, setIsOpen] = useState<boolean>(false)

// null になりうる場合
const [user, setUser] = useState<User | null>(null)

文字列・真偽値の状態

function ToggleButton() {
  const [isOpen, setIsOpen] = useState(false)

  return (
    <button onClick={() => setIsOpen(!isOpen)}>
      {isOpen ? '閉じる' : '開く'}
    </button>
  )
}

オブジェクトの状態

オブジェクトを更新するときはスプレッド構文で既存のプロパティをコピーします。一部だけ上書きしたい場合も同様です。

type User = {
  name: string
  age: number
}

function UserForm() {
  const [user, setUser] = useState<User>({ name: '', age: 0 })

  return (
    <div>
      <input
        value={user.name}
        onChange={(e) => setUser({ ...user, name: e.target.value })}
      />
      <input
        type="number"
        value={user.age}
        onChange={(e) => setUser({ ...user, age: Number(e.target.value) })}
      />
    </div>
  )
}

配列の状態

配列も直接変更せず、新しい配列を返す形で更新します。

function TodoList() {
  const [todos, setTodos] = useState<string[]>([])
  const [input, setInput] = useState('')

  const addTodo = () => {
    setTodos([...todos, input]) // 追加
    setInput('')
  }

  const removeTodo = (index: number) => {
    setTodos(todos.filter((_, i) => i !== index)) // 削除
  }

  return (
    <div>
      <input value={input} onChange={(e) => setInput(e.target.value)} />
      <button onClick={addTodo}>追加</button>
      <ul>
        {todos.map((todo, i) => (
          <li key={i}>
            {todo}
            <button onClick={() => removeTodo(i)}>削除</button>
          </li>
        ))}
      </ul>
    </div>
  )
}

関数型更新

前の状態をもとに更新する場合は関数型更新を使います。非同期処理や複数回の更新が絡む場合に確実です。

// 直接値を渡す(前の状態に依存する場合は注意)
setCount(count + 1)

// 関数型更新(前の状態を確実に参照できる)
setCount((prev) => prev + 1)

useStateを使うべき場面

状況 使う変数
変更時に再レンダリングが必要 useState
再レンダリング不要・DOMの参照 useRef
再レンダリングをまたがず変わらない const

useRefconst との使い分けについては「ReactのuseState・useRef・constの違い」を参照してください。


まとめ

操作 書き方
初期値を設定 useState(初期値)
値を更新 setValue(新しい値)
前の状態から更新 setValue(prev => prev + 1)
オブジェクトを更新 setValue({ ...prev, key: value })
配列に追加 setValue([...prev, item])
配列から削除 setValue(prev.filter(...))

Reactのプロジェクト作成から始める場合は「React + Vite でプロジェクト作成」を参照してください。

複数コンポーネントで状態を共有したい場合は「ReactのuseContext入門」を、複雑な状態遷移には「ReactのuseReducer入門」を参照してください。