React19のuseOptimisticとDnDを組みせるといい感じ
React19のuseOptimisticの使いどころがそんなにわからないなと思っていた昨今ですが、めっちゃハマる使いどころを見つけたので共有します!
useOptimisticってなに?
「楽観的更新をするためのHook」と記載されており、「データの更新→ロード→更新されたあとのデータを表示」の動作のロードの部分を割愛するための仕組みで、確実にデータの更新ができるであろうケースに使用するとアプリを高速で操作できるように見せることができるようです。
useOptimisticの使用の有無の比較
なし
あり
なしのほうがアイテムを離したあとに少しカクついていることがわかります。
DnDでデータを並び替える実装をみる(なし)
ドラックアンドドロップ(以下DnD)で操作を行う場合の多くはDropしたときにDBのデータも書き換えたいものだと思います。今回はリストを並び替えるという動作を例にあげます。
このような実装ではUIに実データをそのまま使用してしまうがちですが、それだとViewで使用しているデータが不整合になる時間が生じてしまい、リアルタイム制が高いDnDの実装だと、先程示したようなカクつきが生まれてしまいます。
DnDでリストを並び替えるコンポーネントをざっと作るとこんな感じです。
※今回はdnd-kitを使用しています。
挙動はデータの更新がされるまでは順番がわかっていないので、一瞬ListItemが元いた場所に戻ろうとしてしまいます。
この解決方法はいくらか想像つくと思いますが、React19からは、useOptimisticを使うのが良さそうです。
useOptimistic を使ったDnDの実装をみる(あり)
今回の並び替えの処理は失敗する可能性が低そうなので、useOptimisticを使用して楽観的更新をします。
補足
ここで実データをuseStateに渡すみたいなことをしています。optimisticItemsはclientで使用するstateです。更新関数は自由に組めるのでuseReducerみたいな感じと捉えるといいでしょう。
そして、useOptimisticの更新関数を、DBを更新する処理と一緒に呼び出してあげましょう。これで、optimisticItemsの更新とDBの更新が行われclientではoptimisticItems をViewに使用しているので動きがいい感じになったというわけです。
また、この更新の処理にはstartTransitionを使用する、更新処理にserver function (action)を使用するようにしましょう。
というわけで、かなりきれいにDnDで並び替えすることができました🎉
ブラウザを更新するとDBの値がちゃんと書き換わっていることを確認できました!
useOptimistic はシンプルなCRUD処理でガンガン使って良さそうだと思いました!
仮にエラーになった場合はToastやスナックバーなどを表示して失敗したことをユーザーに伝えればいいのかなと思います!