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 или функция. При передаче URL в action форма будет вести себя как обычная HTML-форма. При передаче функции в action функция обработает отправку формы. Передаваемая функция action может быть асинхронной и будет вызвана с одним аргументом, содержащим данные формы отправки (данные формы). Свойство action может быть переопределено атрибутом formAction в компонентах <button>, <input type="submit">, или <input type="image">.

Ограничения

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

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

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

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

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 action> позволяет пользователям отправлять формы без JavaScript или до загрузки кода. Это полезно для пользователей со слабым соединением, устройством или отключенным JavaScript и аналогично работе форм, когда URL передается свойству action.

Вы можете использовать скрытые поля формы для передачи данных действию <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> отображается компонентом серверного компонента, и серверная функция передается свойству <form>’s action, форма реализует постепенное улучшение.

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

Для отображения состояния ожидания при отправке формы вы можете вызвать хук 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, { text: sentMessage }]);
  }
  return <Thread messages={messages} sendMessage={sendMessage} />;
}

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

В некоторых случаях функция, вызываемая свойством <form>’s action, может генерировать ошибку. Вы можете обработать эти ошибки, обернув <form> в обработчик ошибок. Если функция, вызываемая свойством <form>’s action, генерирует ошибку, отобразится резервное значение обработчика ошибок.

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. функция, переданная свойству <form>’s action, должна быть серверной функцией.
  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