Spec-Zone.ru › React

<form>

Встроенный браузерный компонент <form> позволяет создавать интерактивные элементы управления для отправки данных.

<form action={search}>
    <input name="query" />
    <button type="submit">Search</button>
</form>
  • Справочник
    • <form>
  • Использование
    • Обработка отправки формы на клиенте
    • Обработка отправки формы с помощью серверной функции
    • Отображение состояния ожидания во время отправки формы
    • Оптимистичное обновление данных формы
    • Обработка ошибок при отправке формы
    • Отображение ошибки отправки формы без JavaScript
    • Обработка нескольких типов отправки

Справочник

<form>

Чтобы создать интерактивные элементы управления для отправки данных, отрисуйте встроенный браузерный компонент <form>.

<form action={search}>
    <input name="query" />
    <button type="submit">Search</button>
</form>

Другие примеры приведены ниже.

Свойства

<form> поддерживает все общие свойства элементов.

action: URL или функция. Если action передан URL, форма будет работать как HTML-компонент формы. Если action передана функция, она будет обрабатывать отправку формы в Transition согласно шаблону свойства Action. Функция, переданная в action, может быть асинхронной; она будет вызвана с одним аргументом, содержащим данные формы, отправленной пользователем. Свойство action можно переопределить атрибутом formAction в компоненте <button>, <input type="submit"> или <input type="image">.

Особенности

  • Если в action или formAction передана функция, HTTP-методом будет POST независимо от значения свойства method.

Использование

Обработка отправки формы на клиенте

Передайте функцию в свойство action элемента form, чтобы вызвать ее при отправке формы. formData будет передан функции в качестве аргумента, чтобы вы могли получить доступ к данным, отправленным формой. Это отличается от обычного HTML action, который принимает только URL-адреса. После успешного выполнения функции action все неуправляемые элементы полей формы сбрасываются.

export default function Search() {
  function search(formData) {
    const query = formData.get("query");
    alert(`You searched for '${query}'`);
  }
  return (
    <form action={search}>
      <input name="query" />
      <button type="submit">Search</button>
    </form>
  );
}

Обработка отправки формы с помощью серверной функции

Отрисуйте <form> с полем ввода и кнопкой отправки. Передайте серверную функцию (функцию, помеченную директивой 'use server') в свойство action элемента form, чтобы вызвать эту функцию при отправке формы.

Передача серверной функции в <form action> позволяет пользователям отправлять формы без включенного JavaScript или до загрузки кода. Это полезно для пользователей с медленным подключением или устройством, а также для тех, у кого отключен JavaScript. Такой подход похож на работу форм, когда свойству action передан URL-адрес.

Чтобы передать данные действию <form>, можно использовать скрытые поля формы. Серверная функция будет вызвана со значениями скрытых полей формы в виде экземпляра FormData.

import { updateCart } from './lib.js';

function AddToCart({productId}) {
  async function addToCart(formData) {
    'use server'
    const productId = formData.get('productId')
    await updateCart(productId)
  }
  return (
    <form action={addToCart}>
        <input type="hidden" name="productId" value={productId} />
        <button type="submit">Add to Cart</button>
    </form>

  );
}

Вместо использования скрытых полей для передачи данных действию <form> можно вызвать метод bind, чтобы передать ему дополнительные аргументы. Это привяжет к функции новый аргумент (productId) в дополнение к formData, передаваемому функции в качестве аргумента.

import { updateCart } from './lib.js';

function AddToCart({productId}) {
  async function addToCart(productId, formData) {
    "use server";
    await updateCart(productId)
  }
  const addProductToCart = addToCart.bind(null, productId);
  return (
    <form action={addProductToCart}>
      <button type="submit">Add to Cart</button>
    </form>
  );
}

Если <form> отрисовывается в серверном компоненте, а серверная функция передается в свойство action элемента <form>, форма прогрессивно улучшается.

Отображение состояния ожидания во время отправки формы

Чтобы отобразить состояние ожидания во время отправки формы, вызовите хук useFormStatus в компоненте, отрисованном внутри <form>, и прочитайте возвращаемое свойство pending.

Здесь мы используем свойство pending, чтобы показать, что форма отправляется.

import { useFormStatus } from "react-dom";
import { submitForm } from "./actions.js";

function Submit() {
  const { pending } = useFormStatus();
  return (
    <button type="submit" disabled={pending}>
      {pending ? "Submitting..." : "Submit"}
    </button>
  );
}

function Form({ action }) {
  return (
    <form action={action}>
      <Submit />
    </form>
  );
}

export default function App() {
  return <Form action={submitForm} />;
}

Подробнее о хуке useFormStatus см. в справочной документации.

Оптимистичное обновление данных формы

Хук useOptimistic позволяет оптимистично обновить пользовательский интерфейс до завершения фоновой операции, например сетевого запроса. В контексте форм этот прием помогает сделать приложения более отзывчивыми. Когда пользователь отправляет форму, интерфейс сразу обновляется в соответствии с ожидаемым результатом, не дожидаясь ответа сервера.

Например, когда пользователь вводит сообщение в форму и нажимает кнопку «Отправить», хук useOptimistic позволяет сразу добавить сообщение в список с пометкой «Отправка…», еще до того, как сообщение будет отправлено на сервер. Такой «оптимистичный» подход создает ощущение быстродействия и отзывчивости. Затем форма пытается отправить сообщение в фоновом режиме. Когда сервер подтверждает получение сообщения, пометка «Отправка…» исчезает.

import { useOptimistic, useState, useRef } from "react";
import { deliverMessage } from "./actions.js";

function Thread({ messages, sendMessage }) {
  const formRef = useRef();
  async function formAction(formData) {
    addOptimisticMessage(formData.get("message"));
    formRef.current.reset();
    await sendMessage(formData);
  }
  const [optimisticMessages, addOptimisticMessage] = useOptimistic(
    messages,
    (state, newMessage) => [
      ...state,
      {
        text: newMessage,
        sending: true
      }
    ]
  );

  return (
    <>
      {optimisticMessages.map((message, index) => (
        <div key={index}>
          {message.text}
          {!!message.sending && <small> (Sending...)</small>}
        </div>
      ))}
      <form action={formAction} ref={formRef}>
        <input type="text" name="message" placeholder="Hello!" />
        <button type="submit">Send</button>
      </form>
    </>
  );
}

export default function App() {
  const [messages, setMessages] = useState([
    { text: "Hello there!", sending: false, key: 1 }
  ]);
  async function sendMessage(formData) {
    const sentMessage = await deliverMessage(formData.get("message"));
    setMessages((messages) => [...messages, { text: sentMessage }]);
  }
  return <Thread messages={messages} sendMessage={sendMessage} />;
}

Обработка ошибок при отправке формы

В некоторых случаях функция, вызываемая свойством action компонента <form>, выбрасывает ошибку. Обработать такие ошибки можно, обернув <form> в границу ошибок (Error Boundary). Если функция, вызываемая свойством action компонента <form>, выбросит ошибку, отобразится резервный интерфейс границы ошибок.

import { ErrorBoundary } from "react-error-boundary";

export default function Search() {
  function search() {
    throw new Error("search error");
  }
  return (
    <ErrorBoundary
      fallback={<p>There was an error while submitting the form</p>}
    >
      <form action={search}>
        <input name="query" />
        <button type="submit">Search</button>
      </form>
    </ErrorBoundary>
  );
}

Отображение ошибки отправки формы без JavaScript

Чтобы отображать сообщение об ошибке отправки формы до загрузки пакета JavaScript в рамках прогрессивного улучшения, необходимо выполнить следующие условия:

  1. <form> должен отрисовываться клиентским компонентом
  2. функция, переданная в свойство action компонента <form>, должна быть серверной функцией
  3. для отображения сообщения об ошибке необходимо использовать хук useActionState

useActionState принимает два параметра: серверную функцию и начальное состояние. useActionState возвращает два значения: переменную состояния и действие. Возвращенное useActionState действие следует передать в свойство action формы. Возвращенную useActionState переменную состояния можно использовать для отображения сообщения об ошибке. Значение, возвращаемое серверной функцией, переданной в useActionState, будет использовано для обновления переменной состояния.

import { useActionState } from "react";
import { signUpNewUser } from "./api";

export default function Page() {
  async function signup(prevState, formData) {
    "use server";
    const email = formData.get("email");
    try {
      await signUpNewUser(email);
      alert(`Added "${email}"`);
    } catch (err) {
      return err.toString();
    }
  }
  const [message, signupAction] = useActionState(signup, null);
  return (
    <>
      <h1>Signup for my newsletter</h1>
      <p>Signup with the same email twice to see an error</p>
      <form action={signupAction} id="signup-form">
        <label htmlFor="email">Email: </label>
        <input name="email" id="email" placeholder="react@example.com" />
        <button>Sign up</button>
        {!!message && <p>{message}</p>}
      </form>
    </>
  );
}

Подробнее об обновлении состояния с помощью действия формы см. в документации useActionState.

Обработка нескольких типов отправки

Формы можно настроить для выполнения разных действий отправки в зависимости от нажатой пользователем кнопки. Каждой кнопке внутри формы можно назначить отдельное действие или поведение, задав свойство formAction.

Когда пользователь нажимает определенную кнопку, форма отправляется и выполняется соответствующее действие, определяемое атрибутами и действием этой кнопки. Например, по умолчанию форма может отправлять статью на проверку, а отдельная кнопка с заданным formAction — сохранять статью как черновик.

export default function Search() {
  function publish(formData) {
    const content = formData.get("content");
    const button = formData.get("button");
    alert(`'${content}' was published with the '${button}' button`);
  }

  function save(formData) {
    const content = formData.get("content");
    alert(`Your draft of '${content}' has been saved!`);
  }

  return (
    <form action={publish}>
      <textarea name="content" rows={4} cols={40} />
      <br />
      <button type="submit" name="button" value="submit">Publish</button>
      <button formAction={save}>Save draft</button>
    </form>
  );
}

© 2013–present Facebook Inc.
Licensed under the Creative Commons Attribution 4.0 International Public License.
https://react.dev/reference/react-dom/components/form

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API