Оптимістичне оновлення - показати результат дії одразу, не чекаючи відповіді сервера: повідомлення з'являється в чаті миттєво, лайк зараховується одразу. Якщо сервер відмовив - повернути як було.
useOptimistic(value, reducer?) (React 19) повертає тимчасовий стан, що діє, поки виконується дія:
import { useOptimistic, useState } from 'react';
function Comments({ initialComments }) {
const [comments, setComments] = useState(initialComments);
const [optimisticComments, addOptimistic] = useOptimistic(
comments,
(current, text) => [...current, { id: `temp-${Date.now()}`, text, sending: true }],
);
async function addComment(formData) {
const text = formData.get('text');
addOptimistic(text); // одразу на екрані
try {
const saved = await api.createComment(text);
setComments((list) => [...list, saved]); // справжні дані
} catch {
toast.error('Коментар не надіслано'); // оптимістичний стан зникне сам
}
}
return (
<>
<ul>
{optimisticComments.map((c) => (
<li key={c.id} style={{ opacity: c.sending ? 0.6 : 1 }}>{c.text}</li>
))}
</ul>
<form action={addComment}>
<input name="text" />
</form>
</>
);
}
Як це працює:
- поки дія виконується,
optimisticComments= результатreducer(чи значення, передане в сеттер); - коли дія завершилася, React повертає
optimisticCommentsдоvalue- тобто доcomments; - успіх:
commentsуже містить збережений коментар - користувач бачить справжні дані; - помилка:
commentsне змінено - тимчасовий коментар просто зникає. Ручного «відкату» не треба.
Умови:
- сеттер оптимістичного стану треба викликати всередині дії (
<form action>,startTransition). Поза нею React попередить, і оптимістичне значення лише мигне; reducerмає бути чистим.
Що враховувати в UX:
- позначати непідтверджені дані (напівпрозорість, «надсилається»), щоб користувач розумів, що вони ще не збережені;
- повідомляти про невдачу - тихе зникнення коментаря гірше за помилку;
- не застосовувати для незворотних дій (оплата, видалення без кошика): оптимістичний «успіх» там вводить в оману;
- тимчасові ключі - згенерований id, щоб React не переплутав оптимістичний елемент зі справжнім.