Асинхронная валидация с React useFormStatus: Обновление статуса формы в асинхронном режиме | MLOG | MLOG

В этом примере:

Объяснение

Хук `useFormStatus` предоставляет информацию о последней отправке формы. В частности, свойство `pending` является булевым значением, которое указывает, находится ли форма в процессе отправки. Свойство `data`, если оно доступно, содержит данные формы. Свойство `action` возвращает функцию, используемую в качестве действия формы.

Продвинутые техники и лучшие практики

1. Debouncing для повышения производительности

В сценариях, где пользователи быстро печатают, например, при проверке имени пользователя или электронной почты, запуск вызова API при каждом нажатии клавиши может быть неэффективным и потенциально перегружать ваш сервер. Debouncing — это техника для ограничения частоты вызова функции. Реализуйте функцию debouncing для задержки валидации до тех пор, пока пользователь не прекратит печатать в течение определенного периода.

            import React, { useState, useCallback, useTransition } from 'react';
import { useFormStatus } from 'react-dom';

function UsernameForm() {
  const [username, setUsername] = useState('');
  const [isPending, startTransition] = useTransition();

  // Debounce function
  const debounce = (func, delay) => {
    let timeoutId;
    return (...args) => {
      clearTimeout(timeoutId);
      timeoutId = setTimeout(() => {
        func(...args);
      }, delay);
    };
  };

  const debouncedHandleSubmit = useCallback(
    debounce(async (formData) => {
      "use server";
      const username = formData.get('username');

      // Simulate an API call to check username availability
      await new Promise(resolve => setTimeout(resolve, 500)); // Simulate network latency

      const isAvailable = username !== 'taken'; // Mock availability check

      if (!isAvailable) {
        throw new Error('Username is already taken.');
      }

      console.log('Username is available!');
      // Perform actual form submission here
    }, 500), // 500ms delay
    []
  );

  return (
    <form action={debouncedHandleSubmit}>
      <label htmlFor="username">Username:</label>
      <input
        type="text"
        id="username"
        name="username"
        value={username}
        onChange={(e) => setUsername(e.target.value)}
      />
      <button type="submit" disabled={isPending}>
        {isPending ? 'Checking...' : 'Submit'}
      </button>
       <StatusComponent />
    </form>
  );
}

function StatusComponent() {
    const { pending, data, method, action } = useFormStatus();

    return (
        <p>
          {pending && "Submitting..."}
          {data && <pre>{JSON.stringify(data)}</pre>}
        </p>
    )
}

export default UsernameForm;

            

В этом улучшенном примере:

2. Throttling для ограничения частоты запросов

В то время как debouncing предотвращает чрезмерные вызовы API в течение короткого периода, throttling гарантирует, что функция вызывается через регулярные промежутки времени. Это может быть полезно, когда вам нужно регулярно выполнять некоторую валидацию, но вы не хотите перегружать свой сервер. Например, для ограничения частоты вызовов API в минуту.

3. Оптимистичные обновления

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

4. Обработка ошибок и обратная связь с пользователем

Предоставляйте пользователю четкие и информативные сообщения об ошибках при сбое валидации. Укажите, какое поле(я) вызвало ошибку, и предложите действия по исправлению. Рассмотрите возможность отображения сообщений об ошибках рядом с соответствующими полями ввода для лучшей видимости.

5. Вопросы доступности (Accessibility)

Убедитесь, что ваши формы доступны для пользователей с ограниченными возможностями. Используйте соответствующие атрибуты ARIA для предоставления семантической информации об элементах формы и их состояниях. Например, используйте aria-invalid для обозначения неверно заполненных полей ввода и aria-describedby для связи сообщений об ошибках с соответствующими полями.

6. Интернационализация (i18n)

При разработке форм для глобальной аудитории учитывайте интернационализацию. Используйте библиотеку, такую как i18next или React Intl, для предоставления переведенных сообщений об ошибках и адаптации макета формы к разным языкам и культурным особенностям. Например, форматы дат и поля адреса различаются в разных странах.

7. Лучшие практики безопасности

Всегда выполняйте валидацию на стороне сервера в дополнение к валидации на стороне клиента. Валидация на стороне клиента в первую очередь предназначена для улучшения пользовательского опыта и может быть обойдена. Валидация на стороне сервера защищает ваше приложение от вредоносного ввода и обеспечивает целостность данных. Санитизируйте пользовательский ввод для предотвращения атак межсайтового скриптинга (XSS) и других уязвимостей безопасности. Также используйте Content Security Policy (CSP) для защиты от XSS-атак.

8. Обработка различных методов отправки формы

Хук useFormStatus хорошо работает как с методами GET, так и с POST. Свойство `method` возвращаемого объекта будет содержать HTTP-метод, использованный для отправки формы. Убедитесь, что ваша серверная логика обрабатывает оба метода соответствующим образом. GET-запросы обычно используются для простого получения данных, в то время как POST-запросы используются для создания или изменения данных.

9. Интеграция с библиотеками для работы с формами

Хотя useFormStatus предоставляет базовый механизм для управления статусом отправки формы, вы можете интегрировать его с более комплексными библиотеками для работы с формами, такими как Formik, React Hook Form или Final Form. Эти библиотеки предлагают расширенные функции, такие как управление состоянием формы, правила валидации и обработка ошибок на уровне полей. Используйте useFormStatus для улучшения пользовательского опыта во время асинхронной валидации в этих библиотеках.

10. Тестирование асинхронной валидации

Пишите юнит-тесты для проверки корректной работы вашей логики асинхронной валидации. Имитируйте вызовы API с помощью библиотек, таких как Jest и Mock Service Worker (MSW). Тестируйте как успешные сценарии, так и сценарии с ошибками, чтобы убедиться, что ваша форма корректно обрабатывает все случаи. Также тестируйте функции доступности ваших форм, чтобы убедиться, что они могут использоваться людьми с ограниченными возможностями.

Примеры из реального мира со всего света

Давайте рассмотрим, как асинхронная валидация используется в различных реальных сценариях по всему миру:

Заключение

Асинхронная валидация — это незаменимый метод для создания надежных и удобных для пользователя форм в React. Используя useFormStatus, debouncing, throttling и другие передовые техники, вы можете предоставлять пользователям обратную связь в реальном времени, предотвращать ошибки и улучшать общий опыт отправки форм. Не забывайте уделять первоочередное внимание доступности, безопасности и интернационализации, чтобы создавать формы, которыми могут пользоваться все и везде. Постоянно тестируйте и отслеживайте свои формы, чтобы убедиться, что они отвечают меняющимся потребностям ваших пользователей и требованиям вашего приложения.