こんにちは!Reactの世界へようこそ。
フロントエンドの深淵を覗き込んでいると、いつか必ず「UIの反応が遅い……」という壁にぶつかりますよね。ボタンを押したのに、サーバーからの返事を待ってから画面が変わるまでのあの「一瞬の空白」。あの待ち時間が、実はユーザーの体験を少しだけ損ねてしまっているんです。
今日は、その待ち時間を魔法のように消し去る「useOptimistic」という素敵な武器について、一緒に紐解いていきましょう。
—
1. 「楽観的更新」ってなんだろう?
まずは専門用語を忘れて、近所のカフェでお会計をする場面を想像してみてください。
あなたは注文を終えて、店員さんに「はい、これ」とクレジットカードを渡します。店員さんはカードを決済端末に通しますが、その間あなたは「決済が完了するまでレジの前で石のように固まって待つ」でしょうか?
……違いますよね。たいていの場合、店員さんが端末を操作している間に、あなたは「あ、あっちの席空いてるな」と視線を移したり、スマホを取り出したりと、次の行動に移る準備をしていますよね。心の中では「まあ、決済は通るだろう(楽観的)」と信じているからです。
Webアプリにおける「楽観的更新(Optimistic Update)」もこれと同じです。
「サーバーへの通信結果を待たずに、とりあえず画面を書き換えてしまう」という手法のこと。ユーザーは「サクサク動く!」と感激し、裏側ではReactがこっそりサーバーと通信して、もし失敗したら「あ、ごめんね」と元に戻す。
この一連の流れを、Reactが最高にスマートに扱えるようにしてくれたのが `useOptimistic` なんです。
—
2. useOptimistic の魔法を覗いてみよう
`useOptimistic` がやっていることは、実はシンプルです。
「今の状態(確定版)」と「とりあえず見せる状態(仮の姿)」の2つを管理して、通信中だけ「仮の姿」を画面に出してくれるんです。
実際にコードで見てみましょう。簡単な「メッセージ送信」の例です。
import { useOptimistic, useState } from ‘react’;
function MessageSender() {
const [messages, setMessages] = useState([‘こんにちは!’]);
// useOptimisticの第一引数は「元の状態」、第二引数は「どうやって仮の状態を作るか」
const [optimisticMessages, addOptimisticMessage] = useOptimistic(
messages,
(currentState, newMessage) => […currentState, newMessage] // 仮のメッセージを配列に追加する
);
async function sendMessage(formData) {
const text = formData.get(‘message’);
// 1. サーバーへ送る前に、まずは楽観的にUIを更新!
addOptimisticMessage(text);
// 2. 実際にサーバーへ通信
const response = await fetch(‘/api/send’, { method: ‘POST’, body: text });
const savedMessage = await response.json();
// 3. 通信が完了したら、本当の状態(messages)を更新して確定させる
setMessages((prev) => […prev, savedMessage]);
}
return (
{optimisticMessages.map((msg, i) =>
{msg}
)}
);
}
—
3. 「副作用」という名の落とし穴
さて、ここからが少しだけプロの話です。`useOptimistic` を使うとき、一番注意しなければならないのが「副作用(useEffectなど)」との同期です。
もし、メッセージを送信した瞬間に「送信完了のログを出す」とか「入力欄を強制的に空にする」といった処理(副作用)を別の場所で動かしていると、大変なことが起きます。
- 問題: 画面は「送信済み」に見えているのに、裏側の通信が失敗していたら?
- 対策: 副作用は「画面の見た目」に引きずられず、「実際のサーバー通信の結果」に基づいて動かすのが鉄則です。
`useEffect` を使って「メッセージが増えたから何か処理をするぞ!」と書くのではなく、`sendMessage` という関数の中で、「通信が成功した時だけ」その後の処理を走らせるようにしましょう。
「画面を見ればわかるでしょ?」という甘えを捨てて、「通信という事実に忠実に処理を行う」。これがReactの現場でバグを減らすための、唯一無二の極意です。
—
最後に:失敗しても大丈夫
初学者の皆さんが一番怖いのは「もしサーバーとの通信が失敗したら、画面とデータの整合性がズレちゃうんじゃないか?」ということですよね。
大丈夫です。`useOptimistic` は、サーバーからの結果が返ってきた時点で、自動的に「仮の姿」を捨てて「正しい状態」へと収束してくれます。もしエラーが起きたら、`setMessages` を呼ばないだけで、Reactは自動的に「さっきの仮の表示」を消し去り、元の画面に戻してくれます。
「楽観的」というのは、いい加減という意味ではありません。
「ユーザーの快適さを最優先にしつつ、失敗した時のケアもちゃんと考えている」という、非常に誠実な設計思想なんです。
最初は難しく感じるかもしれませんが、まずは「ボタンを押した瞬間に画面が変わる」という心地よさを、ぜひあなたのアプリで実装してみてください。その手触りがわかれば、きっとReactのことがもっと好きになれるはずですよ。
また何か壁にぶつかったら、いつでもここへ戻ってきてくださいね。応援しています!

コメント