React Stateを理解する
この記事はReactのHooksの一部であるuseStateを理解するためのものです。
ハマったところで備忘録を書いています。
コンソール上で確認するとStateが更新されていない
こんなことに遭遇した方はおおいのではないでしょうか。
ReactのuseStateは非常に便利で、コンポーネント単位での制作が簡単であり、影響範囲も把握しやすいです。しかし、Stateが更新されるタイミングが分からずに混乱することがあります。この記事では、その理解を深めるために、useStateを使用した簡単なソースコードを用意しました。
今回はボタンを押下すると判定がtrue/falseになるというもの。
App.js
import React, { useState } from 'react';
function SampleState() {
const [isEnt, setIsEnt] = useState(false);
const handleTrueButtonClick = () => {
setIsEnt(true);
console.log(isEnt);
};
const handleFalseButtonClick = () => {
setIsEnt(false);
console.log(isEnt);
};
const RenderClick = () => {
console.log(isEnt);
};
return (
<div>
<h1>Stateの練習</h1>
<h2>ボタン直後の判定: {isEnt.toString()}</h2>
<button onClick={handleTrueButtonClick}>ClickMe True</button>
<br/>
<button onClick={handleFalseButtonClick}>ClickMe False</button>
<br/>
<button onClick={RenderClick}>ClickMe Rendarling</button>
</div>
);
}
export default SampleState;
console.log(isEnt);で内容をコンソール上に判定を表示するようにします。
const handleTrueButtonClick = () => {
setIsEnt(true);
console.log(isEnt);
};
始めはfalseでスタートします。
画面にはfalseで表示されています。
Click Me trueを押下。
コンソール上ではfalseで表示されており、「あれ?表示されない」とソースを見返したが、stateの更新はsetIsEntで(true)としているし、「これは何だろう?」という疑問が残ったので調査をしてみると表示をするまでの理解が存在していました。
公式ではこう表現
書き換えを行うまで変数(isEnt)は更新されないままで、HTMLの差分を検出して表示をし、isEntに格納された値の更新は予約されている状態となる。つまり、console.log(isEnt);はまだレンダリング確定しておらず、stateの値は変わっていません。
ここでレンダークリック関数を押下してみます。
const RenderClick = () => {
console.log(isEnt);
};
レンダーが適用されたのが分かります。
つまり次の変化まで変数の更新がお手の状態になっているのです。
HTMLのみ表示が優先されて非同期で動いている状態。
この結果を条件にもって、即座に値の判定を行いたい場合はどのようにするか。console.log上では値の確認をするかぎり変数の更新つまりレンダーを行ってくれるタイミングでしかありません。
これは変化したstateの状態をかったさらう動き、たとえば
登録ボタンを押す、次のページに行くタイミングの実装のときなど。
すぐに状態の条件に入れたい場合はどうするか?
いったんはconsole.logの動きを確認したい、変更されたタイミングを追うにはどのようにしたらよいでしょうか?
UseEffectを使用する
非同期で行われる関数を終えた後に関数処理をuseEffectで行う。
第二引数に更新の監視を行う関数を入れておく。
そうすると、変化があった関数が一度だけuseEffect関数の処理が行われる。
useEffect(() => {
// 更新後の値が表示される
console.log(isEnt);
}, [isEnt]);
9行目と、27行目で判定の状態が違うのがお分かりだろうか。
変化が分かるように記載する
import React, { useEffect, useState } from 'react';
function SampleState() {
const [isEnt, setIsEnt] = useState(false);
const handleTrueButtonClick = () => {
setIsEnt(true);
console.log(isEnt);
};
const handleFalseButtonClick = () => {
setIsEnt(false);
console.log(isEnt);
};
const RenderClick = () => {
console.log(isEnt);
};
useEffect(() => {
console.log(isEnt); // 更新後の値が表示されます
}, []);
return (
<div>
<h1>Stateの練習</h1>
<h2>ボタン直後の判定: {isEnt.toString()}</h2>
<button onClick={handleTrueButtonClick}>ClickMe True</button>
<br/>
<button onClick={handleFalseButtonClick}>ClickMe False</button>
<br/>
<button onClick={RenderClick}>ClickMe Rendarling</button>
</div>
);
}
export default SampleState;
これで、更新後の値確認が可能になる。
余談だが値の更新には更新関数を記載すると変数内で、返却値が返ってくるので、こちらでも確認はできる。
function SampleState() {
const [isEnt, setIsEnt] = useState(0);
const handleTrueButtonClick = () => {
setIsEnt(n => n + 1);
console.log(isEnt);
};
Reactは非同期で行われる更新を値のゲッター、セッターにしてくれていると思いとどめ、組み込みを行っていくことが肝要である。
ご覧いただきありがとうございました。 サポートしていただいたお金は開発費にかけさせていただきます。