😜

Optimistic Update (楽観的更新)でストレスのないUXを実現する

2022/06/27に公開

ファンタラクティブのエンジニアの 太田 です。
Optimistic Updateについて検討する機会があったので紹介します。

SPAでAPIを利用しデータを更新しその結果を画面に反映させる場合、APIのレスポンスを待つ必要があります。
しかし、レスポンスを待ってから画面に反映すると、ユーザーが操作してから画面に反映されるまでに時間がかかり、UXが悪くなってしまいます。
そんな悩みを解決するのがOptimistic Updateです。

課題

ユーザーの操作によりデータを更新し、その結果が返ってくるまで1秒かかるとしたら、1秒以上経ってから画面に反映されるため、もっさりしたシステムに感じます。
1秒ならまだマシですが、これがもっと長かったらどうでしょう。

またデータ更新後、別のデータ取得APIを呼び出して更新したデータを再取得する仕組みになっているかもしれません。
その場合、それぞれのAPIのレスポンスが1秒で返ってきたとしても2秒以上待たされることになります。

Optimistic Updateの仕組み

想定結果を反映する

Optimistic UpdateはAPIのレスポンスを待たずに想定する結果を画面に反映してしまいます。
これによってユーザーの操作後すぐ画面に反映されます。
またAPIのレスポンスが返ってきたら再度画面に反映します。
2度画面の更新が発生するので、画面のチラツキが発生する可能性はありますが、想定したとおりのレスポンスが返ってきたら、画面上変化はなくユーザーにはわかりません。

ロールバック

通信が発生している以上、API呼び出し結果が不正となることがあります。
もしAPI呼び出しが不正となった場合は、フロントで保持している更新前のデータで再更新をします。
画面上1度更新されたデータが、数秒後に古い値に戻るので違和感はありますが、不正な値を持ったまま後続の操作してしまうことはなくなります。

サンプル

Vue

React (React Queryでrefetch)

あとがき

Optimistic Updateは便利ですが、なんでもOptimistic Updateを行えばいいかといえばそうではありません。
処理後に画面遷移が発生するものなど基本的にOptimistic Updateは必要ないと思います。
エラーが発生した場合もロールバックするより、エラー画面に遷移させるなど処理ごとに適切な設計をする必要あります。
Optimistic Updateの実装は、そうでないものに比べて難しくフロントの複雑さが増します。
サーバーサイドから取得したデータを表示するだけではなく、フロントでstateを扱うことになります。
そのためうまく実装をしないとサーバーサイドで保持するデータとフロントのstateの整合性が合わなくなります。
例えばボタンを短時間に複数回押されないように、想定結果の反映はするけどレスポンスが返ってくるまで別の操作はできなくする。
finally句などでAPIの呼び出し結果が成功/失敗に関わらずrefetchを行い、画面に反映するなど考慮が必要だと思います。

最後に画面へのデータの反映の流れの図を張っておきます。


画面へのデータの反映の流れ

ファンタラクティブテックブログ

Discussion