<form>
Встроенный браузерный компонент <form> позволяет создавать интерактивные элементы управления для отправки информации.
<form action={search}>
<input name="query" />
<button type="submit">Search</button>
</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-пакета для постепенного улучшения требует:
-
<form>должен отображаться серверным компонентом. - функция, переданная свойству
<form>’saction, должна быть серверной функцией. - для отображения сообщения об ошибке используется хук
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