Reactを学び始めると、useStateで値を更新すると画面が変わるという動き自体は理解できても、なぜ画面が変わるのかまでははっきり理解しにくいことがあります。
この記事では、Reactのコンポーネントがどのタイミングで再実行されるのか、useStateの更新が何をしているのか、そしてstateを更新した直後に新しい値を読めない理由までを順に整理してみました。
結論
最初に結論を書くと、Reactの再レンダリングを理解するうえで重要なのは次の3点です。
- コンポーネント関数は初回表示のときだけでなく、更新時にも再び実行される
-
useStateが返すstate更新用の関数を呼ぶと、Reactは次の再レンダリングを予約する - stateの更新結果は、すぐに変数に反映されるのではなく、次のレンダリングで反映される
この3点が分かると、useStateは単に値を保持する仕組みではなく、再レンダリングのきっかけを作る仕組みでもあることが見えてきます。
再レンダリングとは何か
Reactでは、stateが更新されたり、親コンポーネントから受け取るpropsが変わったりすると、コンポーネント関数が再び実行されます。これを再レンダリングと呼びます。
import { useState } from 'react';
export default function Counter() {
const [count, setCount] = useState(0);
console.log('render:', count);
return (
<div>
<p>{count}</p>
<button onClick={() => setCount(count + 1)}>+1</button>
</div>
);
}
このコードでは、最初の表示時にCounterが実行されます。
そのあとsetCount(count + 1)が呼ばれると、Reactはもう一度Counterを実行し、更新後の画面を計算します。
ここで大事なのは、画面上で変化して見える部分だけを、その場で直接書き換えているわけではないということです。
Reactはコンポーネント関数全体をもう一度実行して、その結果をもとに更新後の表示内容を決めます。
useStateが再レンダリングにつながる仕組み
useStateは、単に値を保存する仕組みではありません。
stateを更新するための関数を通して、Reactに「次のレンダリングが必要です」と伝える役割も持っています。
const [count, setCount] = useState(0);
-
countは、現在のレンダリングで参照できる state の値 -
setCountは、stateを更新し、次の再レンダリングを予約するための関数
普通の変数との違いはここです。
let count = 0;
count = 1;
このコードではJavaScript上の変数は変わりますが、その変数はReactが管理している state ではないため、再レンダリングのきっかけにはなりません。
そのため、表示内容も変わりません。
一方でsetCount(1)を呼ぶと、Reactはstateの更新を認識し、再レンダリングを行います。
state更新の直後に新しい値を読めない理由
ここは初学者が混乱しやすいところです。
const [count, setCount] = useState(0);
function handleClick() {
setCount(count + 1);
console.log(count);
}
このconsole.log(count)では、増加後の値ではなく、更新前のcountが出力されます。
理由は、setCountがその場でcountを直接書き換えるのではなく、次のレンダリングに向けて state の更新を予約するからです。
そのため、setCountの直後に書いたコードからは、更新後の値を参照することはできません。
直前のstateを使って更新したいときの書き方
次のように、同じ処理の中でstate更新を続けて書く場合を考えます。
setCount(count + 1);
setCount(count + 1);
一見すると、countが2回増えるように見えます。
しかし、この2行で使われているcountは、どちらもレンダリング時点の値になります。
そのため、2回とも同じ値をもとにcount + 1を計算します。
直前の更新結果を使って、さらに次の stateを計算したい場合は、関数形式で書きます。
setCount(prev => prev + 1);
setCount(prev => prev + 1);
この書き方では、Reactが前回の更新結果をprevとして渡してくれます。
そのため、連続したstate更新を行うことができます。
ここまでの整理
ここまでを整理すると、Reactで画面が変わる流れは次のようになります。
- ボタン操作などで
setStateを呼ぶ - useStateで次のレンダリングを予約する
- コンポーネント関数が再実行される
- 新しい結果が画面に反映される
この流れが分かるとuseStateは「値を保存するもの」という理解だけではなく、再レンダリングのきっかけを作るものでもあると分かります。
まとめ
Reactの再レンダリングを理解するうえで大事なのは、次の整理です。
- コンポーネント関数は
useStateでの更新時に再実行される -
useStateの更新は次のレンダリングを予約する -
setStateの直後に更新後の値をすぐに読めるわけではない - 連続して更新するときは関数形式で書く
useStateは「値を保持する仕組み」だけでなく、「Reactに次の表示計算を促す仕組み」として理解すると、コードの動きを追いやすくなります。