Перейти к содержанию
  • Лента
  • Категории
  • Последние
  • Метки
  • Популярные
  • Пользователи
  • Группы
Свернуть
exlends
Категории
  1. Главная
  2. Категории
  3. Фронтенд
  4. React 19: useOptimistic и useActionState для пессимистичных форм с progressive enhancement

React 19: useOptimistic и useActionState для пессимистичных форм с progressive enhancement

Запланировано Прикреплена Закрыта Перенесена Фронтенд
react 19useoptimisticuseactionstate
1 Сообщения 1 Постеры 73 Просмотры
  • Сначала старые
  • Сначала новые
  • По количеству голосов
Ответить
  • Ответить, создав новую тему
Авторизуйтесь, чтобы ответить
Эта тема была удалена. Только пользователи с правом управления темами могут её видеть.
  • hannadevH Не в сети
    hannadevH Не в сети
    hannadev
    написал в отредактировано
    #1

    Обложка: React 19: useOptimistic с useActionState для пессимистичных обновлений форм с progressive enhancement и fallback состояниями

    React 19 притащил useOptimistic и useActionState - хуки, которые меняют правила игры с формами. Они позволяют делать пессимистичные обновления: UI показывает реальное состояние с фолбэками, пока сервер думает. Это решает боль задержек и спиннеров - юзер сразу видит, что происходит, даже если сетка легла.

    Progressive enhancement здесь в теме: формы работают без JS, а с React’ом добавляется магия optimistic’а. Зачем это? Меньше бойлерплейта, чище стейт, надежнее UX. Погнали разбирать на примерах.

    useActionState: стейт действий без лишнего кода

    useActionState берет на себя управление стейтом асинхронных экшенов - pending, success, error в одном хуке. Вместо кучи useState для loading/error/success пишешь одну строку. Форма подключается через action={formAction}, и React сам обновляет UI по результату.

    Представь форму логина: юзер жмет submit, сервер проверяет креды. Без этого хука пришлось бы вручную сетить isLoading=true, потом обрабатывать ответ. С useActionState стейт всегда актуальный, кнопка дизаблится на pending. Это упрощает код в 2-3 раза, особенно с серверными экшенами.

    Ключевые фичи:

    • Возвращает [state, action] - state это объект с pending/error/lastSuccess.
    • Поддерживает progressive enhancement: без JS форма шлет POST на сервер.
    • Интегрируется с useOptimistic для гибридных обновлений.
    Свойство Описание Пример
    pending true во время запроса disabled={pending}
    error Строка с ошибкой сервера {error &&

    {error}

    }
    lastSuccess Результат успеха {lastSuccess?.message}

    Пример простейшей формы:

    const [state, formAction] = useActionState(loginAction, {error: null});
    <form action={formAction}>
      <input name="email" />
      <button disabled={state.pending}>Login</button>
      {state.error && <p style={{color: 'red'}}>{state.error}</p>}
    </form>
    

    Нюанс: initialState задай null или {}, чтобы избежать фликера.

    useOptimistic для пессимистичных обновлений

    useOptimistic рендерит UI сразу по ожидаемому результату, откатывает при ошибке. Для пессимистичных форм это идеал: показывай фолбэк (спиннер, “отправляем…”), пока сервер не ответил. Комбинируй с useActionState - optimisticState берет реальный стейт и мутирует его.

    Возьми список тасок: юзер добавляет новую, UI сразу показывает “sending…”. Сервер ответил - обновляем, ошибка - роллбэк. Без этого хука приходилось дублировать стейт optimistic/real. Теперь один хук - два стейта: реальный и UI-версия.

    Как это работает:

    • const [optimisticTasks, addOptimistic] = useOptimistic(tasks, (state, newTask) => [...state, {text: newTask, sending: true}]);
    • В formAction: addOptimistic(formData.get(‘task’)); await sendToServer();
    • При ошибке стейт откатывается автоматически.

    Плюсы пессимистичного подхода:

    • Fallback’и: всегда показывай pending-state, даже оффлайн.
    • Progressive: форма работает без React.
    • Rollback: ошибка? optimisticState синхронится с реальным.
    Optimistic vs Pessimistic Когда юзать
    Optimistic Лайки, комментарии (предполагаем успех)
    Pessimistic Формы с критичными данными (логин, оплата)

    Код для тасок:

    function Tasks({tasks, sendTasks}) {
      const [optimisticTasks, addOptimisticTask] = useOptimistic(tasks, (state, newTask) => [...state, {text: newTask, sending: true}]);
      async function formAction(formData) {
        addOptimisticTask(formData.get('task'));
        await sendTasks(formData);
      }
      return (
        <>
          {optimisticTasks.map(t => <div>{t.text} {t.sending && '(отправляем...)'}</div>)}
          <form action={formAction}><input name="task" /><button>Add</button></form>
        </>
      );
    }
    

    Комбо: useActionState + useOptimistic с progressive enhancement

    Соединяем хуки: useActionState управляет form-state, useOptimistic - UI-обновлениями. Форма шлет серверный экшен, optimistic добавляет фолбэк сразу. Progressive enhancement на месте: без JS - обычный POST, с JS - мгновенный фидбек.

    Пример - редактирование профиля. Юзер меняет email, форма показывает “saving…” optimistic’но, сервер валидирует. Ошибка? Роллбэк + error из useActionState. Это убивает спиннеры и лоадеры - UI живой всегда.

    Шаги реализации:

    1. Создай серверный action с async/await.
    2. Подключи useActionState для стейта формы.
    3. Добавь useOptimistic для списка/формы.
    4. В action: optimistic update -> await server -> sync.
    const [state, formAction] = useActionState(updateProfile, {error: null});
    const [optimisticProfile, updateOptimistic] = useOptimistic(profile, (st, newEmail) => ({...st, email: newEmail, saving: true}));
    // В action: updateOptimistic(formData.get('email')); return await api.update();
    

    Сравнение подходов:

    Подход Boilerplate UX Progressive
    useState + useEffect Высокий Спиннеры Нет
    useActionState solo Низкий Хороший Да
    + useOptimistic Минимальный 🔥 Идеал Да

    Важно: uncontrolled inputs - не синхронизируй value с state, пусть FormData рулит.

    Пессимистичные фолбэки - когда оптимизм подведет

    Фолбэки в пессимистичном стиле - это pending-states в optimisticState. Показывай “loading”, “error”, не жди сервера. С useFormStatus внутри формы - кнопка сама знает pending. Комбо с роутерами типа Next.js - серверные actions на стероидах.

    Думай о слабом интернете: optimistic рендерит фолбэк, useActionState ловит error. Нет нужды в глобальном loading - локальные хуки все тянут.

    Фичи для продакшена:

    • Rollback в catch: addOptimistic((prev) => prev - 1) для лайков.
    • Hydration: SSR + client optimistic синхронятся.
    • Error boundaries не нужны - стейт сам хэндлит.

    Код фолбэка:

    function LikeButton({likes}) {
      const [optLikes, addOpt] = useOptimistic(likes, (prev) => prev + 1);
      async function handle() {
        addOpt();
        try { await fetch('/like'); } catch { addOpt((p) => p - 1); }
      }
      return <button onClick={handle}>❤️ {optLikes}</button>;
    }
    

    Гибридные паттерны выходят за рамки форм

    useOptimistic + useActionState работают не только с формами - лайки, чат, CRUD. Остается копать интеграцию с TanStack Query или SWR для кэша. Подумай о custom hooks для типичных сценариев: optimisticDelete, optimisticPatch. В React 19 это база для быстрых apps - меньше костылей, больше нативности.

    1 ответ Последний ответ
    0

    Здравствуйте! Похоже, вас заинтересовала эта беседа, но у вас ещё нет аккаунта.

    Надоело каждый раз пролистывать одни и те же посты? Зарегистрировав аккаунт, вы всегда будете возвращаться на ту же страницу, где были раньше, и сможете выбирать, получать ли уведомления о новых ответах (по электронной почте или в виде push-уведомлений). Вы также сможете сохранять закладки и ставить лайки постам, чтобы выразить свою благодарность другим участникам сообщества.

    С вашими комментариями этот пост мог бы стать ещё лучше 💗

    Зарегистрироваться Войти

    Категории

    • Главная
    • Новости
    • Фронтенд
    • Бекенд
    • Языки программирования

    Контакты

    • Сотрудничество
    • info@exlends.com

    © 2024 - 2026 ExLends, Inc. Все права защищены.

    Политика конфиденциальности
    • Войти

    • Нет учётной записи? Зарегистрироваться

    • Войдите или зарегистрируйтесь для поиска.
    • Первое сообщение
      Последнее сообщение
    0
    • Лента
    • Категории
    • Последние
    • Метки
    • Популярные
    • Пользователи
    • Группы