# setStateの直後にconsole.logしても古い値が出る理由
こんにちは、白々さじきです。
今回は、`setState` の直後に `console.log` しても古い値が出る理由についてまとめます。
React を使い始めたころ、「setStateを呼んだのになんで更新されないの?」と詰まったので、備忘録も兼ねて書きます。(私の学習のために生成AIに作らせた文章を一部加筆修正しました。)
## 結論
`setState` を呼んでも、その場でstateは更新されません。stateが新しい値になるのは次のレンダリング時です。直後に `console.log` すると古い値が出るのはこの仕組みのためです。
## setState はその場でstateを変えない
Reactのstateはレンダリングのたびに「スナップショット(その瞬間の写真)」として扱われます。
`setState` を呼ぶと「次のレンダリングでこの値を使ってね」とReactに伝えるだけで、現在のスナップショットは変わりません。
“`tsx
const Counter: FC = () => {
const [count, setCount] = useState(0);
const handleClick = () => {
setCount(count + 1);
// この時点の count はまだ 0(スナップショットが変わっていない)
console.log(count); // 0
};
return
;
};
“`
ボタンを押すと画面の数字は `1` に変わりますが、`console.log` には `0` が出ます。`setState` が「次のレンダリングで更新してほしい」という予約をしただけで、今のスナップショットの `count` はまだ `0` のままです。
## stateの最新値を確認するには
stateの最新値を確認したいときは、コンポーネントのトップレベルに `console.log` を置きます。
“`tsx
const Counter: FC = () => {
const [count, setCount] = useState(0);
// ここに置くと、レンダリングのたびに最新値が出る
console.log(count);
const handleClick = () => {
setCount(count + 1);
console.log(count); // ← ここでは古い値が出る
};
return
;
};
“`
レンダリングのたびにコンポーネント関数全体が再実行されるため、トップレベルの `console.log` には常に最新のstateが渡されます。
## おまけ: 開発中に console.log が2回出る理由
デバッグ中に「なんか2回出る」と感じたことがあるかもしれません。これは `
` が原因です。
“`tsx
// main.tsx
“`
開発環境では、副作用のバグを検出するためにコンポーネントを意図的に2回レンダリングします。本番ビルドでは1回だけになるので、機能的な問題はありません。
「2回出るからおかしい」ではなく「StrictModeが正常に動いている」と理解しておくと混乱しなくなります。
## まとめ
– `setState` を呼んでも、その場でstateは変わらない
– stateが反映されるのは次のレンダリング時
– `console.log(state)` で最新値を確認するには、コンポーネントのトップレベルに置く
– 開発中に2回レンダリングされるのはStrictModeの仕様(バグではない)
最初は「setStateを呼んだのに反映されない」と焦りましたが、スナップショットという考え方を知ってからすんなり理解できました。React初心者の方の参考になれば幸いです。
## 参考リンク
– [state as a snapshot(スナップショットとしてのstate)](https://ja.react.dev/learn/state-as-a-snapshot)
– [StrictMode](https://ja.react.dev/reference/react/StrictMode)
サポートのお願い
下記リンクからお買い物いただけると、ブログ運営のための費用が増え、有料サービスを利用した記事作成が可能になります。ご協力よろしくお願いします!
コメント