Stop Using Loading Spinners: Master Optimistic UI in React ⚡

#react#optimistic-ui#tanstack-query#frontend

TL;DR

Использование Optimistic UI в React позволяет мгновенно обновлять интерфейс, создавая иллюзию быстрого отклика приложения. В статье рассмотрим, как реализовать эту технику с помощью TanStack Query (бывший React Query) для улучшения пользовательского опыта.

Введение: контекст и актуальность

В традиционной веб-разработке пользовательский интерфейс часто блокируется на время выполнения запросов к серверу, что делает приложение медленным и неудобным. Optimistic UI — это подход, при котором интерфейс мгновенно обновляется, а запрос выполняется в фоновом режиме. Если запрос завершится ошибкой, интерфейс возвращается к предыдущему состоянию. Этот подход особенно полезен для микро-взаимодействий, таких как отметка задачи как выполненной или лайк комментария.

Основная часть с примерами кода

Проблема с Loading Spinners

Традиционный подход с использованием спиннеров заставляет пользователя ждать завершения запроса, что снижает воспринимаемую производительность приложения. Optimistic UI позволяет избежать этого, мгновенно обновляя интерфейс.

Реализация Optimistic UI с TanStack Query

Рассмотрим пример реализации Optimistic UI для отметки задачи как выполненной в приложении управления проектами.

// components/TaskItem.tsx
import { useMutation, useQueryClient } from '@tanstack/react-query';
import axios from 'axios';

export default function TaskItem({ task }) {
    const queryClient = useQueryClient();

    const mutation = useMutation({
        // 1. Фактический API вызов
        mutationFn: (newStatus: boolean) => {
            return axios.patch(`/api/tasks/${task.id}`, { completed: newStatus });
        },

        // 2. Оптимистичное обновление (выполняется сразу при вызове mutate())
        onMutate: async (newStatus) => {
            // Отменяем текущие запросы, чтобы они не перезаписали оптимистичное обновление
            await queryClient.cancelQueries({ queryKey: ['tasks'] });

            // Сохраняем предыдущее состояние для возможного отката
            const previousTasks = queryClient.getQueryData(['tasks']);

            // Оптимистично обновляем кэш мгновенно
            queryClient.setQueryData(['tasks'], (oldData: any) => {
                return oldData.map((t: any) => 
                    t.id === task.id ? { ...t, completed: newStatus } : t
                );
            });

            // Возвращаем объект контекста с сохраненным предыдущим состоянием
            return { previousTasks };
        },

        // 3. Если запрос завершился ошибкой, используем контекст для отката
        onError: (err, newStatus, context) => {
            queryClient.setQueryData(['tasks'], context?.previousTasks);
            alert("Не удалось обновить задачу. Пожалуйста, попробуйте снова.");
        },

        // 4. Всегда обновляем данные после успешного или неудачного запроса для синхронизации с сервером
        onSettled: () => {
            queryClient.invalidateQueries({ queryKey: ['tasks'] });
        },
    });

    return (
        <div className="flex items-center gap-3">
            <input 
                type="checkbox" 
                checked={task.completed} 
                onChange={(e) => mutation.mutate(e.target.checked)} 
            />
            <span className={task.completed ? "line-through" : ""}>
                {task.title}
            </span>
        </div>
    );
}

Влияние на воспринимаемую производительность

Реализация Optimistic UI делает приложение более отзывчивым и приятным в использовании. Пользователи могут быстро взаимодействовать с интерфейсом без необходимости ждать завершения запросов.

Практическое применение

Optimistic UI особенно полезен в приложениях с интенсивным взаимодействием пользователя, таких как управление задачами, социальные сети или платформы электронной коммерции. Использование TanStack Query упрощает реализацию этой техники, делая код более читаемым и поддерживаемым.

Заключение

Optimistic UI — это мощный подход для улучшения пользовательского опыта, который позволяет мгновенно обновлять интерфейс и маскировать задержки сервера. Использование TanStack Query делает реализацию этой техники простой и эффективной, что позволяет создавать более отзывчивые и приятные в использовании приложения.


Источник: https://dev.to/iprajapatiparesh/stop-using-loading-spinners-master-optimistic-ui-in-react-4m9c