Ручная реализация оптимистичных обновлений
Локально применяйте оптимистичное состояние, ставьте мутацию в очередь и явно обрабатывайте успешные и неуспешные случаи
«Ручная реализация оптимистичных обновлений» — бесплатный урок React Academy на CoddyKit. Это урок 2 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения React Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс React Academy содержит 4 уроков всего.
Состояние до операции изменения данных
Ручные оптимистичные обновления начинаются с локального состояния компонента, инициализированного данными сервера: const [items, setItems] = useState(serverItems). Именно это локальное состояние вы отображаете и оптимистично изменяете. Данные, полученные с сервера, NOT следует изменять напрямую — храните управляемую локальную копию.
Шаг оптимистичного обновления
Когда пользователь запускает операцию изменения данных (нажимает «Добавить», «Нравится» или «Удалить»), немедленно обновите состояние до вызова API: setItems(prev => [...prev, newItem]). Интерфейс сразу отражает изменение. Только после этого отправьте фактический сетевой запрос.
Сохранение предыдущего состояния
Перед оптимистичным обновлением сохраните текущее состояние: const previousItems = items. Этот снимок является целью отката. Если вызов API завершится ошибкой, восстановите это значение. Храните его в переменной, а не в состоянии, поскольку оно нужно только на время ожидания завершения операции изменения данных.
Выполнение вызова API
После оптимистичного обновления асинхронно выполните вызов API. Обработайте его с помощью конструкции для перехвата ошибок. При успехе можно дополнительно повторно получить данные, чтобы синхронизировать их с состоянием сервера, или довериться оптимистичному состоянию, если сервер вернёт те же данные. При ошибке используйте сохранённое предыдущее состояние для отката.
Откат при ошибке
В блоке обработки ошибки операции изменения данных вызовите: setItems(previousItems). Это восстановит состояние, существовавшее до оптимистичного обновления. После отката покажите уведомление об ошибке. Пользователи понимают, что редкие ошибки случаются, — но они не могут мириться с незаметным несоответствием.
Показ уведомления об ошибке
После отката покажите сообщение об ошибке: «Не удалось сохранить изменения. Повторите попытку.» — и добавьте кнопку «Повторить», которая снова запускает ту же операцию изменения данных. Это даёт пользователям возможность управлять ситуацией. Сочетание отката, уведомления об ошибке и повторной попытки позволяет корректно обработать сбой, не блокируя весь интерфейс.
Проблема временного идентификатора
При оптимистичном добавлении нового элемента сервер ещё не назначил ему настоящий идентификатор. Создайте для оптимистичного элемента временный идентификатор: const tempId = crypto.randomUUID(). Используйте его как ключ элемента в списке. После успешного ответа API замените временный идентификатор настоящим идентификатором, назначенным сервером.
Согласование временных идентификаторов
После успешного создания элемента сервер возвращает настоящий идентификатор. Обновите состояние, заменив временный элемент: setItems(prev => prev.map(item => item.id === tempId ? { ...item, id: serverResponse.id } : item)). Это согласование гарантирует, что последующие операции используют правильный идентификатор сервера.
Проблема состояния гонки
Если пользователь запускает две операции изменения данных с очень маленьким интервалом, ответы могут прийти не по порядку. Ответ второй операции может прийти раньше первого, а откат первой операции — перезаписать корректное состояние, полученное от второй. Это состояние гонки, характерное для оптимистичного интерфейса.
Сериализация мутаций для предотвращения состояний гонки
Один из способов решить проблему состояний гонки — сериализовать мутации с помощью очереди. Пока мутация выполняется, отключайте кнопку запуска (устанавливая состояние isSubmitting в true). Разрешайте следующую мутацию только после завершения предыдущей. Это снижает отзывчивость, но гарантирует правильный порядок обновления состояния.
Шаблон оптимистичного удаления
Для операций удаления: сохраните предыдущие элементы, отфильтруйте удаляемый элемент из состояния, вызовите API удаления и при ошибке выполните откат. Удаление проще создания (не требуется согласовывать ID), но принципы те же. Перед вызовом API можно добавить небольшую задержку и показать вариант «отменить», чтобы пользователь мог отменить удаление.
Временный ID в оптимистичных обновлениях
Почему добавленным оптимистично элементам нужен временный ID?
Итоги урока: ручные оптимистичные обновления
Ручной подход: сохраните previousItems, установите новое состояние с помощью setItems, вызовите API, а при ошибке выполните откат с помощью setItems(previousItems) и покажите ошибку. При добавлении используйте crypto.randomUUID() как временный ID, а после успешного выполнения согласуйте его с ID сервера. Предотвращайте состояния гонки, отключая кнопку запуска на время выполнения мутаций. Откат, уведомление и повторная попытка — стандартный пользовательский сценарий при ошибке.
Часто задаваемые вопросы
Урок «Ручная реализация оптимистичных обновлений» бесплатный?
Да — полный текст урока «Ручная реализация оптимистичных обновлений» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс React Academy, подпишись на CoddyKit PRO. Курс React Academy содержит 4 уроков всего.
Чему я научусь в уроке «Ручная реализация оптимистичных обновлений»?
Локально применяйте оптимистичное состояние, ставьте мутацию в очередь и явно обрабатывайте успешные и неуспешные случаи Ты практикуешь React Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать React Academy?
Предыдущий опыт не требуется. React Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 2 из 4.
Сколько времени занимает урок «Ручная реализация оптимистичных обновлений»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке React Academy?
Да. Каждый урок React Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Что такое оптимистичный интерфейс и когда его использовать
- Ручная реализация оптимистичных обновлений
- Откат при ошибке и разрешение конфликтов
- Оптимистичные шаблоны с React Query и Zustand