Що таке useOptimistic
Що таке useOptimistic()
useOptimistic()- це React-хук, який дозволяє тимчасово показувати оновлений стан в UI, поки виконується асинхронна дія (наприклад, відправлення форми, додавання коментаря, видалення елемента тощо).
Іншими словами: він допомагає зробити інтерфейс відповідним і "живим", навіть якщо запит до сервера займе 1-2 секунди.
Сигнатура
const [optimisticState, addOptimistic] = useOptimistic(baseState, updateFn);| Аргумент | Опис |
|---|---|
baseState | Поточний реальний стан (наприклад, список коментарів, масив задач тощо) |
updateFn | Функція (state, newValue) => newState, що описує, як відобразити "оптимістичний" стан |
| Повертає | [optimisticState, addOptimistic] - поточний стан (з урахуванням оптимізму) і функція для його тимчасової зміни |
Приклад з життя
Припустимо, ти робиш чат, де повідомлення відправляються на сервер. Користувач натискає "Надіслати", але відповідь від API приходить через секунду. Без оптимізму UI зависає - повідомлення з'являється лише після відповіді.
З useOptimistic() ти можеш показати нове повідомлення одразу,
а потім React автоматично оновить UI, коли сервер відповість.
Приклад: додавання коментаря
import { useOptimistic, useActionState } from 'react';
async function postComment(prevState, formData) {
const comment = formData.get('comment');
await api.addComment(comment);
return { success: true };
}
export default function Comments({ comments }) {
const [state, formAction] = useActionState(postComment, null);
const [optimisticComments, addOptimistic] = useOptimistic(
comments,
(currentComments, newComment) => [
...currentComments,
{ id: Math.random(), text: newComment, pending: true },
]
);
async function handleSubmit(formData) {
const comment = formData.get('comment');
addOptimistic(comment); // миттєво показати новий коментар
await formAction(formData); // дочекатися сервера
}
return (
<form action={handleSubmit}>
<ul>
{optimisticComments.map(c => (
<li key={c.id}>
{c.text} {c.pending && '(sending...)'}
</li>
))}
</ul>
<input name="comment" />
<button type="submit">Send</button>
</form>
);
}Тут:
useOptimisticстворює "віртуальний" список коментарів з новим повідомленням одразу;- Коли сервер відповість, React замінить оптимістичний стан на реальний;
- Користувач одразу бачить, що його коментар з'явився.
Інші приклади
Видалення елемента
const [optimisticTodos, removeOptimistic] = useOptimistic(
todos,
(current, id) => current.filter(t => t.id !== id)
);
async function handleDelete(id) {
removeOptimistic(id); // миттєво приховати
await api.deleteTodo(id); // потім сервер підтвердить
}Лайки
const [optimisticLikes, toggleOptimistic] = useOptimistic(
likes,
(current, delta) => current + delta
);
async function handleLike() {
toggleOptimistic(1);
await api.likePost();
}Як це працює під капотом
- Ти зберігаєш "реальний" стан (наприклад,
commentsчиlikes). - React створює поверх нього "оптимістичний" стан, який застосовується миттєво.
- Коли Action завершилась (або дані оновилися з сервера), React відкидає оптимістичний стан і синхронізується з реальним.
- Якщо операція завершилася помилкою - React автоматично "відкотить" UI до попереднього стану.
Відмінність від ручного підходу (useState)
Без useOptimistic тобі довелося б писати:
setComments([...comments, newComment]); // вручну
try {
await api.addComment(newComment);
} catch {
setComments(oldComments); // відкат
}Проблеми:
- потрібно зберігати старий стан для відкату,
- складно синхронізувати з іншими оновленнями,
- може конфліктувати з concurrent rendering.
З useOptimistic:
- React сам відстежує "віртуальні" зміни,
- автоматично синхронізує і відкочує стан,
- працює безпечно в конкурентному режимі.
Коли використовувати useOptimistic
Підходить для:
- Інтерфейсів із затримками відповіді (форми, коментарі, лайки, кошики);
- Списків і таблиць, де додаються/видаляються елементи;
- UX-оптимізації - користувач бачить дію "одразу".
Не варто використовувати:
- Для даних, де помилка має блокувати дію (наприклад, платежі);
- Для стану, що залежить від складних транзакцій на сервері;
- Коли "оптимістична" версія може збити користувача з пантелику.
Порівняння з іншими хуками React 19
| Хук | Призначення |
|---|---|
useActionState() | Керує станом асинхронної дії (результат, помилка, pending) |
useFormStatus() | Відстежує статус відправлення конкретної форми |
useOptimistic() | Тимчасово оновлює UI для миттєвого зворотного зв'язку |
useTransition() | Робить оновлення "низькопріоритетними", але не оптимістичними |
Комбо-приклад: useOptimistic + useActionState
async function addTask(prev, formData) {
const task = formData.get('task');
await api.addTask(task);
return { success: true };
}
export default function TaskList({ tasks }) {
const [state, formAction] = useActionState(addTask, null);
const [optimisticTasks, addOptimistic] = useOptimistic(
tasks,
(list, newTask) => [...list, { id: Math.random(), text: newTask, pending: true }]
);
async function handleSubmit(formData) {
const task = formData.get('task');
addOptimistic(task);
await formAction(formData);
}
return (
<form action={handleSubmit}>
<ul>
{optimisticTasks.map(t => (
<li key={t.id}>{t.text} {t.pending && '(saving...)'}</li>
))}
</ul>
<input name="task" />
<button type="submit">Add</button>
</form>
);
}Користувач бачить нову задачу миттєво, React оновлює її остаточно, коли сервер підтвердить.
Підсумок
useOptimistic()- це React-хук для створення миттєвого відгуку UI при асинхронних змінах, поки сервер обробляє дію.Він ідеально підходить для UX, де важливе відчуття "швидкості", при цьому React сам керує відкатом і узгодженням даних.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.