ReactでuseStateの値が更新されない仕様を理解する
はじめに
React で useState をよく使用すると思いますが、setState した後に State 値を確認したいということはよくあるかと思います。
しかし setState したのにも関わらず更新した値が確認できず、うまく動作しているか把握できないケースが発生しました。
私と同様にこの沼にハマってしまう方が多いのではないかと思いこの記事を書いてみます。
※これから React を勉強していこうという方に読んでいただければ幸いです。
1.state を更新したのにコンソールで更新された値が表示されない例
以下のコンポーネントで試してみようと思います
export const Sample: FC = () => {
const [textValue, setTextValue] = useState("");
const onChangeText = (e: ChangeEvent<HTMLInputElement>) => {
setTextValue(e.target.value);
console.log(textValue)
};
return (
<div className="sample">
<h2>テキスト入力</h2>
<input type="text" onChange={onChangeText} value={textValue} />
</div>
);
}
テキストボックスに値を入力するたびに値がコンソールにはき出されるようになっています。
テキストボックスに「1」を入れてみます
コンソールには何も出力されてません。続いて「2」を入力してみます
「2」を入力したタイミングで「1」がコンソールに出力されました。
このことからsetTextValue
した値は1つ遅れで更新されていることがわかります。
なぜこのようなことが起こっているかというと、
setTextValue
は非同期で処理されておりコードの上から順に更新が行われていない- React の仕様で state は次のレンダリングされるタイミングまで反映されない
というようになっているからです。今回の場合、
「1」を入力
↓
setTextValue
↓
コンソール出力無
↓
再レンダリング[textValue が更新される]
↓
「2」を入力
↓
setTextValue
↓
コンソール出力「1」
となるわけです。因みに再レンダリングは state が更新されたタイミングで行われます。
2 更新する値の確認方法
state を更新直後に値を確認したい場合、setState に入れる値をそのままコンソール出力すれば良いです。
export const Sample: FC = () => {
const [textValue, setTextValue] = useState("");
const onChangeText = (e: ChangeEvent<HTMLInputElement>) => {
setTextValue(e.target.value);
console.log(e.target.value) // ここを更新値に変更
};
return (
<div className="sample">
<h2>テキスト入力</h2>
<input type="text" onChange={onChangeText} value={textValue} />
</div>
);
}
このようなコードだとで更新したい値を直後に確認できます。
setState で state 値はちゃんと更新されているので、ここは信用して先に進みましょう。。
(私はこれがちゃんと動いているか確認したかったですが、仕様上なので仕方ないですね)
export const Sample: FC = () => {
const [textValue, setTextValue] = useState("");
const onChangeText = (e: ChangeEvent<HTMLInputElement>) => {
setTextValue(e.target.value);
console.log(textValue)
};
return (
<div className="sample">
<h2>テキスト入力</h2>
<input type="text" onChange={onChangeText} value={textValue} />
<h2>{textValue}</h2>
</div>
);
}
まとめ
state の挙動を理解していないとここで沼にはまってしまい、他のコード箇所が間違っているのではないかと疑ってしまいます。
state はレンダリング後でしか反映されないということを念頭においてコードを記載していくのをおすすめします。
参考資料
Discussion