カミナシ エンジニアブログ

株式会社カミナシのエンジニアが色々書くブログです

UIが嘘をつく? UXデザインにおける「楽観的な更新」とSPAでの作り方

f:id:kaminashi-developer:20210201121737j:plain

こんにちは、デザインエンジニアのショウです。

突然ですが、UI/UX デザインにおいて、「楽観的な更新」という言葉を聞いたことがありますか?あまり聞いたことがなくても、実は日常にたくさん存在しています。

例えば、 twitterfacebook のいいねボタン。いいねをタップした直後に色がつくのですが、実はサーバーへのリクエスト送信と UI 上のいいねの色付きが同時に発生しています。つまりサーバーからの通信結果待たずに UI を更新しています。

他に、trello でタスクカードを隣の列に移動したり、iMessage や Facebook メッセンジャーでのメッセージの送信、Kindle アプリで途中までしかダウンロード出来てない本が読めることなども楽観的な更新です。

図:楽観的な更新を採用しない時と採用した時のメッセージ送信のUI (引用元

楽観的な更新の意義

早くも 1968 年頃 Robert Miller 氏の論文 "Response Time in Man-Computer Conversational Transactions" で、(コンピューターの)キーを押した後のビジュアル的なフィードバックは 0.1 から 0.2 秒以内に出すべきだと書かれていました。

人間の一回まばたきの速さは平均で 0.1 から 0.15 秒だと言われているので、何かの操作からビジュアルフィードバックまでの遅延時間がそれ以内に納まれば、結果が即座に反映されるためサクサクな操作感が得られます。楽観的な更新は、ユーザーが操作した直後に UI 側が更新されるので、物理的な通信速度などに囚われず遅延のない UI が実現できます。

f:id:kaminashi-developer:20210201115130j:plain

ja.wikipedia.org

また、サーバーからのレスポンスを待たずに UI 更新するので、レスポンスを待つ間、ユーザーの操作をブロックする必要もなくなります。前の操作にブロックされず次の動作に移れるため、ソフトウェアで作業のフローが中断されにくくなります。

f:id:kaminashi-developer:20210201115233j:plain

ja.wikipedia.org

適しているケース

では、どういうどころが楽観的な更新に適しているかというと、

API のリライアビリティがあり、到達性が保証される

楽観的な更新は、高い成功率を前提とした手法です。更新が失敗するときのハンドリングはもちろん組み込まれていますが、失敗率が高いと逆に楽観的な更新を採用しなかった時よりも、マイナスな心理をユーザーに与えてしまいます。

フロントエンド側でレスポンスの結果を予測できる

例えば、バックエンドより複雑な機械学習から結果を返す場合、フロントエンド側で結果の予測ができないので楽観的な更新は作れません。

フロントエンド側、事前にエラーになる要素を排除できる

楽観的な更新は高い成功率を前提とするので、できれば、バックエンドと同じデータバリデーションをフロントエンドでも実装してリクエストの成功率を高めます。

実装例

楽観的な更新の実装をみてみましょう。想定するシーンは、Twitter のようないいねボタンを押す部分の処理です。(いいね数の更新の部分はだいぶ複雑になるので割愛します)

ポイントは、

  • UI を先行して更新する
  • レスポンスが成功した場合の対応(楽観的に更新してあるので、一般的には何もしない)
  • サーバー・レスポンスがエラーになるときのハンドリング(ロールバック
  • オフラインの対応

辺りです。

使うライブラリは redux-offlineredux-thunk です。

github.com

github.com

まず、ミドルウェア層を現在の store に追加します:

f:id:kaminashi-developer:20210201115459p:plain

次に action に楽観的な更新の部分、データ通信の部分、通信成功した部分、失敗した時のロールバックの部分を定義します。

f:id:kaminashi-developer:20210201115523p:plain

最後に reducer の action 部分のデータ処理を書きます。

f:id:kaminashi-developer:20210201115541p:plain

これで、Twitter のいいねを押したときに、サーバーへリクエストを送信すると同時に、UI は先行して更新するようになります。サーバーから成功したレスポンスが返ってきた時、UI 側は何もせずに、エラーになった場合のみ、リクエスト送信する前の状態にロールバックします。

redux-offline を使うメリットは、アプリケーションがオフラインになってしまう時に、サーバーへのリクエストが一度ペンディング状態になります。この時、UI 側の楽観的な更新には影響しません。ネットが復帰した時に溜まったリクエストが自動的に再開します。

これで楽観的な更新が一通り実装されました。redux-offlineredux-thunk の組み合わせの他に redux-optimistic-ui も使えます。 redux 以外に mst を使う場合は mst-gql がおすすめです。是非ユーザー体験の改善に使ってみてください。

github.com

github.com

最後に募集の宣伝です!弊社ではデザイナー、エンジニア(正社員・副業)を募集しています。興味がある、話を聞いてみたい、応募したいという方をお待ちしております!

open.talentio.com

楽観的な更新に関するおすすめ記事:

uxplanet.org

www.smashingmagazine.com

medium.com

uxdesign.cc

medium.com