LoginSignup
73
45

【React】setCount(count + 1)みたいな書き方が良くないよーってお話

Last updated at Posted at 2023-05-16

はじめに

よく技術記事でuseStateが説明されていたり、reactの全般的なもので

.jsx
  const countUp = () => {
    setCount(count + 1)
  };

みたいな書き方をされているものはありませんか?

自分も以前は恥ずかしながら上記の書き方をしていました。
サンプルコードでは問題がない場合が多いですが以下の不具合が含まれる可能性があります。

どうすればいいの?

結論!!

  const countUp = () => {
    setCount((prev) => prev + 1)
  };

と記述してください。
setCount(count + 1)でも動くじゃん!と思うかもしれません。
これから理由について説明していきます。

バグが起きるユースケース

import { useState } from 'react'
import './App.css'

function App() {
  const [count,setCount] = useState(0) 

  const handleClick = () => {
    setCount(count + 1)
    setCount(count + 1)
  }

  return (
  <>
    <h1>useState</h1>
    <button onClick={handleClick}>count is {count}</button>
  </>
  )
}

export default App

実際に環境構築したい方は下の記事参考に作ってください

上記のコードぱっと見countボタンを押せば count が 2ずつ増えるように思えるかもしれません。
しかし実際の挙動は以下のようになります。

download.gif

countが1ずつしか増えませんよね...
なぜこうなるのか解説していきます。

setCountは再レンダリングされる直前に実行され、countは定数

実際に出力してみると分かりやすいかもしれません

  const handleClick = () => {
    setCount(count + 1)
    console.log(count)
  }

とすると、実際に出力されるのは初期値が0だとしても0+1で1と思うかもしれませんが0が出力されます。
更新関数setCountはstateの次のレンダリングの値とするという指示をするだけで、現時点では初期に設定した0という値が参照されます。

実際に書き出すとこんな感じですね。

import { useState } from 'react'
import './App.css'

function App() {
  const [count,setCount] = useState(0) 

  const handleClick = () => {
    setCount(0 + 1)
    setCount(0 + 1)
  }

  return (
  <>
    <h1>useState</h1>
    <button onClick={handleClick}>count is {count}</button>
  </>
  )
}

export default App

上記を見れば一目瞭然かなと思います!

まとめ

setCountのような更新関数は即座に実行されるのではなく、再レンダリング前に予約される処理ということ。
countはあくまで定数ということを意識すれば頭にスッと入るかなと思います。
正しく動いてたとはいえ前記事でsetCount(count + 1)と書いてたのはすいません

【2023年最新】React(v18)完全入門ガイド|Hooks、Next.js、Redux、TypeScript

本記事は上記のセクション5を参考に作成しました!
Reactを体系的学べてかつ、仕組み自体も図を用いて解説されていて分かりやすいです💪

最後まで読んで頂きありがとうございました!

73
45
6

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
73
45