<form>
Canary
Расширения React для <form> в настоящее время доступны только в каналах React canary и experimental. В стабильных релизах React, <form> работает только как встроенный браузерный HTML-компонент встроенный браузерный HTML-компонент. Подробнее о каналах выпуска React можно узнать здесь.
Встроенный браузерный компонент <form> позволяет создавать интерактивные элементы управления для отправки информации.
<form action={search}>
<input name="query" />
<button type="submit">Search</button>
</form>
Справочник
<form>
Для создания интерактивных элементов управления для отправки информации используйте встроенный браузерный компонент <form>.
<form action={search}>
<input name="query" />
<button type="submit">Search</button>
</form> См. дополнительные примеры ниже.
Свойства
<form> поддерживает все общие свойства элементов.
action: URL или функция. Когда в action передается URL, форма будет вести себя как обычный HTML-элемент формы. Когда в action передается функция, она будет обрабатывать отправку формы. Функция, переданная в action может быть асинхронной и будет вызвана с одним аргументом, содержащим данные формы отправленной формы данные формы. Свойство action может быть переопределено атрибутом formAction в компоненте <button>, <input type="submit">, или <input type="image">.
Ограничения
- Когда функция передается в
actionилиformAction, метод HTTP будет POST независимо от значения свойстваmethod.
Использование
Обработка отправки формы на клиенте
Передайте функцию в свойство action формы, чтобы запустить её при отправке. formData будет передана функции в качестве аргумента, так что вы сможете получить доступ к данным, отправленным формой. Это отличается от стандартного действия 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> ); }
Обработка отправки формы с помощью Server Action
Отобразите <form> с полем ввода и кнопкой отправки. Передайте Server Action (функцию, помеченную 'use server') свойству action формы, чтобы запустить её при отправке формы.
Передача Server Action в <form action> позволяет пользователям отправлять формы без JavaScript или до загрузки кода. Это полезно для пользователей с медленным подключением, устройством или отключенным JavaScript, и аналогично тому, как работают формы, когда в свойство action передаётся URL.
Вы можете использовать скрытые поля формы для предоставления данных в действию <form>. Server Action будет вызвана с данными скрытого поля формы как экземпляр 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> отображается компонентом Server Component, и Server 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, { text: sentMessage }]); } return <Thread messages={messages} sendMessage={sendMessage} />; }
Обработка ошибок отправки формы
В некоторых случаях функция, вызываемая свойством <form> формы, выбрасывает ошибку. Вы можете обработать эти ошибки, обернув <form> в Error Boundary. Если функция, вызываемая свойством <form> формы, вызывает ошибку, отобразится запасное значение Error Boundary.
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-пакета для постепенного улучшения необходимо:
-
<form>рендерится компонентом Server Component - функция, передаваемая свойству
<form>формы, должна быть Server Action - для отображения сообщения об ошибке используется хук
useActionState
useActionState принимает два параметра: Server Action и начальное состояние. useActionState возвращает два значения: переменную состояния и действие. Действие, возвращаемое useActionState, должно быть передано в свойство action формы. Переменная состояния, возвращаемая useActionState, может быть использована для отображения сообщения об ошибке. Значение, возвращаемое Server Action, передаваемой в 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://18.react.dev/reference/react-dom/components/form