ReactでTodoアプリなどのCRUDアプリを作っていると、こんなコードを書く場面が出てきます。
const handleAddTodo = () => {
setTodos([...todos, { id: todoId, title: todoTitle }])
setTodoId(todoId + 1)
}
「これで動くし、問題なくない?」と思っていたのですが、調べてみると prev を使った書き方のほうが安全 だということがわかりました。
💡prevを使った書き方
const handleAddTodo = () => {
setTodos(prev => [...prev, { id: todoId, title: todoTitle }])
setTodoId(prev => prev + 1)
}
setTodos や setTodoId にコールバック関数を渡す書き方です。
引数名(ここでは prev)は何でもOKですが、慣習として prev〇〇 と書くことが多いです。
❓️何が違うの?
Reactのstate更新は非同期で処理されます。
prevなしの場合、todos や todoId は「その時点でコンポーネントが持っている値」を参照します。
連続してstate更新が走るような場面では、古い値を参照してしまうリスクがあります。
// ❌ 連続呼び出しで危険なケース
setTodoId(todoId + 1) // todoId が古い値かもしれない
setTodoId(todoId + 1) // 同じ古い値を参照してしまう可能性
prevありの場合、Reactが「更新キューの最新値」を引数として渡してくれるので、常に正しい値を元に更新できます。
// ✅ 常に最新値を受け取れる
setTodoId(prev => prev + 1)
setTodoId(prev => prev + 1) // 直前の更新結果を受け取れる
💡どちらを使えばいいの?
| ケース | どちらを使うか |
|---|---|
| 学習・シンプルなCRUDアプリ | どちらでも動く |
| 前の値を元にstateを更新する | prev 推奨 |
| 連続したstate更新がある | prev ほぼ必須 |
| ポートフォリオ・実務コード | prev に統一するのがベター |
学習用のシンプルなアプリなら prevなしでも実用上は問題ありません。
ただ、「前の値を元にstateを更新するときは prev を使う」 という習慣は今から身につけておくと良いと思います。
✅️まとめ
- スプレッド構文でstateに要素を追加するとき、
prevを使うとより安全 -
prevという名前に特別な意味はなく、Reactが最新のstateを引数として渡してくれる - シンプルなアプリでは動作に差はないが、ベストプラクティスとして
prevを使う習慣をつけておくのがおすすめ
自分もCRUDアプリを作りながら気づいた点なので、同じところで迷っている方の参考になれば嬉しいです!