stateとは
「時間とともに変わる値」を扱うための仕組み
React でいう state(ステート)は、ひと言でいうと「画面の中で変わる値」です。
逆に言うと、「一度決めたら変わらないもの」は state ではありません。
例えば、次のようなものは state になりやすいです。
入力フォームの中身
カウンターの数字
チェックボックスがオンかオフか
モーダルが開いているか閉じているか
これらはユーザーの操作によって変化します。
React は「state が変わったら、そのstateを使っているコンポーネントの見た目をもう一度描き直す(再レンダリングする)」という仕組みで動いています。
イメージとしては、
「コンポーネントの“今の状態”を記録しておく箱」
「その箱の中身を変えると、Reactが自動で画面を最新の状態に合わせてくれる」
これが state です。
useStateの基本
useStateは「状態を作るためのReactの関数」
React では、useState という特別な関数(フック)を使って state を作ります。
この useState は React から提供される公式の機能です。
一番基本的な形はこうです。
import { useState } from "react";
function Example() {
const [value, setValue] = useState(初期値);
return (
<p>{value}</p>
);
}
JSXここで重要なのは三つです。
useState(初期値) を呼ぶと、「state」と「そのstateを更新するための関数」のペアが返ってくる。
配列の分割代入で [value, setValue] のように変数名をつけている。value は「今の値」、setValue は「その値を変えるための専用関数」。
例えば、文字列を状態として持ちたいときはこう書きます。
const [text, setText] = useState("初期の文字");
JSX数値を状態として持ちたいときはこうです。
const [count, setCount] = useState(0);
JSXuseState に渡した値が、その state の最初の値(初期値)になります。
名前のつけ方の慣習
useState で受け取る二つの変数には、よくこの形で名前をつけます。
左側が「今の値」
右側が「set + 値の名前(先頭大文字)」
たとえば、
[count, setCount][isOpen, setIsOpen][name, setName]
などです。
この形にしておくと、「あ、これは state とその更新関数だな」とすぐに分かるので、コードが読みやすくなります。
ボタンで数値を増やす
最小のカウンターコンポーネントを作る
useState の一番有名で分かりやすい例が「カウンター」です。
ボタンをクリックするたびに数字が増える、という動きを作ってみましょう。
import { useState } from "react";
function Counter() {
const [count, setCount] = useState(0);
function handleClick() {
setCount(count + 1);
}
return (
<div>
<p>現在のカウント: {count}</p>
<button onClick={handleClick}>1増やす</button>
</div>
);
}
export default Counter;
JSXこのコンポーネントの流れを丁寧に分解します。
最初に useState(0) を呼び出して、count の初期値を 0 にしている。
ボタンがクリックされると handleClick 関数が呼ばれる。handleClick の中で setCount(count + 1) を実行している。setCount が呼ばれると、count の値が 1 増え、React はこのコンポーネントを再レンダリングする。
再レンダリング後は、count が新しい値(前の値より1増えた値)になり、<p>現在のカウント: {count}</p> の表示も更新される。
ユーザーから見ると、
ボタンを押すたびに数字が 1 ずつ増える
という動きになっています。
setCount は「直接代入ではなく、Reactに“更新して”とお願いする」
ここで重要なのは、「count に直接代入してはいけない」という点です。
これはダメな例です。
function handleClick() {
count = count + 1; // NG
}
JSXこう書いても、React は「state が変わった」と認識してくれません。
画面も更新されず、バグの原因になります。
React に「state が変わったよ、画面を更新していいよ」と伝えるためには、
必ず setCount のような「set 関数」を使う必要があります。
function handleClick() {
setCount(count + 1); // OK
}
JSX「stateの値は直接書き換えず、必ず setXxx で更新する」というルールは非常に重要です。
再レンダリングの概念
「stateが変わると、そのコンポーネントがもう一度実行される」
React の大きな特徴は、「state が変わると UI が自動で最新状態に更新される」という点です。
この「描き直し」のことを「再レンダリング」と呼びます。
先ほどの Counter コンポーネントでは、次のようなサイクルが起きています。
初回レンダリング
コンポーネント関数が呼ばれ、useState(0) によって count は 0、setCount が用意される。
JSX が返され、「現在のカウント: 0」と描画される。
ボタンクリック → state 更新
ユーザーがボタンをクリックすると、handleClick が呼ばれ、setCount(count + 1) が実行される。
再レンダリング
React が「state が更新された」と認識し、Counter コンポーネントをもう一度呼び出す。
このとき、count は 1 になっている。
新しい JSX が返され、「現在のカウント: 1」と描画され直す。
この「コンポーネント関数が再度呼ばれる」というのがポイントです。
関数コンポーネントは、「呼ぶたびに今の state を使って UI を計算し直す関数」と見るとイメージしやすくなります。
画面を書き換えるのは React の仕事、自分は「どうあるべきか」だけ書く
昔ながらのやり方だと、DOM操作(document.getElementById(...) など)で自分で画面を書き換えていました。
React では、その低レベルな操作はすべて React に任せます。
開発者がやるのは、
「今の state に対して、画面はこうあるべき」と JSX で宣言すること
「このタイミングで state をこう変えてほしい」と setXxx で伝えること
だけです。
あとは React が、
どこが変わったのか
どう最小限にDOMを更新するか
などを全部面倒見てくれます。
この「状態が変わったら UI を作り直す(宣言的UI)」という考え方に慣れると、
「ボタン押されたらこの要素を書き換えて…」のような細かい手作業から解放されます。
まとめ(useStateの感覚をつかむ)
state は「コンポーネントの中で変化していく値」で、入力値やカウント、オンオフ状態など「時間とともに変わるもの」を管理するために使う。useState は「state本体」と「stateを更新するための関数」のセットを作るためのReactの関数で、const [value, setValue] = useState(初期値); の形で使う。
カウンターのように、ボタンのクリックイベントで setCount(count + 1) を呼ぶことで、state を更新し、そのたびにコンポーネントが再レンダリングされて画面が最新の状態に保たれる。
state の値は直接代入で書き換えず、必ず setXxx 関数を使うことが重要で、これが React に「UI を描き直していいよ」と伝える唯一の方法になる。
次のステップとしては、自分で次のようなコンポーネントを作ってみると良いです。
ボタンを押すと増えるカウンター
ボタンを押すと「表示/非表示」が切り替わるテキスト
入力した文字をそのまま画面にリアルタイム表示するフォーム
どれも useState と「再レンダリング」の感覚をつかむのにうってつけの練習になります。
