以下のことを言いたいわけではない。
- useStateの更新関数を実行した直後に、stateの値が更新されてない
- 更新されるのはコンポーネントが再レンダリングされた後なのは知っている
- 問題にしたいのは、DOMに反映されない(=再レンダリングされない)こと
- 更新関数に渡したオブジェクトがstateと同じため、stateの更新を検知でない
- 今回発生したのは、文字列型や数値型のstateを更新した時
どうのようなコードで発生したか
以下のコードは、ボタンを押すと、stateが更新され、それをDOM上に反映するコンポーネントだ。
実際には、もっと複雑なコードであるのだが、ともかく文字列や数値のstateを更新しているのに、
再レンダリングが行われない、すなわちCount: {count}
が更新されない、という現象に遭遇した。
import { useState } from 'react';
const Counter = () => {
const [count, setCount] = useState(0);
const handleClick = () => {
setCount(count + 1);
// ここでcountの値が更新されないのは当然
console.log(count);
};
return (
<div>
<p>Count: {count}</p>
<button onClick={handleClick}>Click me</button>
</div>
);
};
export default Counter;
ボタンをクリックしても表示がかわらず、何秒待っても反映されないのだが、
おかしなことに、マウスを動かしてボタンからフォーカスを外すとコンポーネントが再レンダリングされた。
何を言っているのかわからねえと思うが、俺も(ry
解消方法
タブを閉じて新しいタブで開き直す。
Chromeで閲覧して発生していた現象だったのだが、Firefoxで確認したところ問題なく動く(ボタンクリック後に即時に再レンダリングされる)ことに気づき、
Chromeのタブを閉じて新しいタブで当該ページを開き直したところ解消した。
雑な解釈だが、タブを開きすぎていたりしたせいで、ブラウザの挙動が重くなっていたということなのだろう。
Reactの再レンダリングは非同期である。普通はstate更新すると即座(に思えるくらいには速く)再レンダリングが実行される。
だが、ブラウザの状況が劣悪だと、stateが更新された後もずっと再レンダリングを実行しないということがありうるようだ。
(そしてボタンのフォーカスをはずすとか、ひょんな拍子で再レンダリングしたりする)
このような現象は検索しても全然出てこない。
もしかしたら、同じ問題に躓くひともいるだろうと思い、ここに書き残しておく。