はじめに
React
を使用している方なら以下のようなコードは数え切れないほどに書いていることでしょう。
const [state, setState] = useState(0);
今回は、useState()
から返されるステート更新用関数は非同期で実行される、という点について書いていきます。
実験
以下のコードで試してみましょう。
const [count, setCount] = useState(0); const onClick = () => { setCount(count + 1); console.log(count); // 最初にクリックしたときは「0」が出力される } return <div> <div>{count}</div> <button onClick={onClick}>increment!</button> </div>
上記の例を見ても分かる通り、setCount(count + 1)
が実行されても、直後にcount
が更新されていないことがわかります。
さらに、例えば以下のようにdoubleCountUp
があるとしましょう。
const doubleCountUp = () => { setCount(count + 1); setCount(count + 1); }
上記のdoubleCountUp
が実行されたとしても、再レンダー後にはcount
は1しか増えません。
解決案
以下のように修正することで、再レンダー後に期待した結果が得られるようになります。
const doubleCountUp = () => { setCount(previous => previous + 1); setCount(previous => previous + 1); }
なぜ
なぜsetState
が非同期に実行されるかを説明しておきます。
仮に同期的に実行されるとすると、setState()
の呼び出しごとにコンポーネントの再レンダーが発生してしまい、パフォーマンスが非常に悪くなってしまいます。
そのため、React
はsetState
をまとめて処理することで再レンダーを最小限に留めています。
参考
What’s with functions inside setState? | by nashe omirro | Oct, 2021 | Medium