React を使ううえで、state はとても重要な概念です。
当たり前のように使っているからこそ、改めてここで整理しておこうと思います。
この記事では、state の基本的な役割、書き方、更新の流れ、使うときの注意点についてまとめます。
1. state とは
state は、コンポーネントの状態を表す値です。
Web アプリケーションでは、画面はさまざまな状態を持っています。
例えば、以下のようなものです。
- 入力フォームに入力された文字
- モーダルが開いているかどうか
- チェックボックスが選択されているかどうか
- API から取得した一覧データ
- ローディング中かどうか
このような、画面の中で変化する値を管理するのが state です。
React では、この state を使って値を管理し、その値に応じて画面を再描画します。
つまり、state は**「画面を変化させるための元になる値」**だと考えれば分かりやすいです。
2. 実際の書き方
一般的に React で state と言うと、React Hooks の useState を使うケースを指すことが多いです。
基本の書き方は以下です。
const [state, setState] = useState(初期値);
useState は配列を返し、以下の 2 つを受け取ります。
- 1つ目: 現在の state の値
- 2つ目: state を更新するための関数
例えば、入力された名前を管理したい場合は以下のように書けます。
import { useState } from "react";
function Sample() {
const [name, setName] = useState("");
return (
<div>
<input value={name} onChange={(e) => setName(e.target.value)} />
<p>入力された名前: {name}</p>
</div>
);
}
この例では、name が state です。
input に文字を入力すると setName が呼ばれ、name の値が更新されます。
その結果、画面の表示も更新されます。
3. state 更新の流れ
state は、以下のような流れで更新されます。
1. イベントが発生する
例えば、入力欄に文字を入力する、ボタンを押す、といった操作です。
2. state 更新関数を呼ぶ
setState や setName のような更新関数を呼びます。
3. state の値が更新される
React が新しい state を受け取ります。
4. 再レンダリングされる
更新された state をもとに、コンポーネントが再び実行され、画面表示が更新されます。
先ほどの入力欄の例でも、文字を入力すると setName が呼ばれ、state が更新されます。
React はその更新をもとに再レンダリングを行い、画面の表示を最新の状態に保ちます。
4. state を使うときの注意点
state は便利ですが、更新したい箇所すべてに使えばよいわけではありません。
使いどころを誤ると、コードが複雑になったり、不要な再レンダリングが発生したりして、画面の描画性能に影響することがあります。
特に意識したいのは、以下のような点です。
4-1. 画面に関係する「変化する値」に使う
state は、画面表示に関係する値や、ユーザー操作によって変化する値に使います。
例えば以下は state で管理することが多いです。
- 入力値
- 開閉フラグ
- 選択状態
- API の取得結果
4-2. 他の値から導出できるものは state にしない
他の state や props から計算できる値は、state にせず、レンダリングのたびに計算すれば十分です。
例えば以下のようなケースです。
// ❌ わざわざ state にしなくてよい
const [fullName, setFullName] = useState("");
useEffect(() => {
setFullName(firstName + " " + lastName);
}, [firstName, lastName]);
// ✅ レンダリング時に計算すればよい
const fullName = firstName + " " + lastName;
もう一つ、よくある例として、配列のフィルタリングがあります。
// ❌ フィルタ結果を state にしている
const [filteredItems, setFilteredItems] = useState([]);
useEffect(() => {
setFilteredItems(items.filter((item) => item.active));
}, [items]);
// ✅ レンダリング時に計算すればよい
const filteredItems = items.filter((item) => item.active);
このように、その場で求められる値をわざわざ state にすると、管理が増えるだけでなく、不要な再レンダリングの原因にもなります。
「本当に state で持つ必要があるか」は一度立ち止まって考えた方がよいです。
4-3. state 更新はすぐには反映されない
setState を呼んだ直後に、同じレンダリング内で最新の値を参照することはできません。
これは React の仕様で、state の更新は次の再レンダリング時に反映されるためです。
例えば以下のようなコードです。
setCount(count + 1);
console.log(count); // まだ更新前の値が表示される
この console.log(count) では、更新後の値ではなく更新前の値が表示されます。
React の state は、普通の変数のように「代入した瞬間に書き換わる」わけではありません。
**「次の再レンダリングで新しい値が使われる」**という仕組みだと理解しておくと、混乱しにくくなります。
4-4. 前の値をもとに更新するときは関数形式を使う
前回の値をもとに更新したい場合は、以下のように関数形式で書くと安全です。
setCount((prevCount) => prevCount + 1);
setCount(count + 1) のように直接値を渡す書き方だと、同じレンダリング内で複数回呼んだ場合に、count がすべて同じ値を参照してしまい、期待通りに更新されないことがあります。
関数形式であれば、React が保持している最新の値を引数として受け取れるため、連続した更新でも正しく動作します。
5. まとめ
state は React の根幹をなす概念で、画面に表示される「変化する値」を管理するためのものです。
ただし、何でも state にすればよいわけではなく、本当に管理が必要な値かどうかを考えることが大切です。
基本的な部分ですが、ここを丁寧に理解しておくと、React の挙動全体が見通しやすくなると感じています。
6. 参考
今回は state の基本的な部分のみを整理しました。
React 公式ドキュメントでは、state の更新や設計についてさらに詳しく解説されています。
基本を理解したうえであわせて読むと、より理解が深まると思います。