| title | <form> |
|---|
O componente <form> do navegador embutido permite que você crie controles interativos para enviar informações.
<form action={search}>
<input name="query" />
<button type="submit">Search</button>
</form>Para criar controles interativos para enviar informações, renderize o componente <form> do navegador embutido.
<form action={search}>
<input name="query" />
<button type="submit">Search</button>
</form><form> suporta todas as props de elementos comuns.
action: uma URL ou função. Quando uma URL é passada para action, o formulário se comportará como o componente de formulário HTML. Quando uma função é passada para action, a função irá manipular o envio do formulário seguindo o padrão de props de Action. A função passada para action pode ser async e será chamada com um único argumento contendo os dados do formulário do formulário enviado. A prop action pode ser substituída por um atributo formAction em um componente <button>, <input type="submit"> ou <input type="image">.
- Quando uma função é passada para
actionouformAction, o método HTTP será POST, independentemente do valor da propmethod.
<<<<<<< HEAD
Passe uma função para a prop action do formulário para executar a função quando o formulário for enviado. formData será passado para a função como um argumento para que você possa acessar os dados enviados pelo formulário. Isso difere da ação HTML convencional, que aceita apenas URLs. Após a execução da função action, todos os elementos de campo não controlados no formulário são redefinidos.
Pass a function to the onSubmit event handler to run code when the form is submitted. By default, the browser sends the form data to the current URL and refreshes the page, so call e.preventDefault() to override that behavior.
This example reads the submitted values with new FormData(e.target), which collects every field by its name. This keeps the inputs uncontrolled. If you instead control an input with state, read from that state on submit rather than from FormData.
export default function Search() {
function handleSubmit(e) {
// Prevent the browser from reloading the page
e.preventDefault();
// Read the form data
const form = e.target;
const formData = new FormData(form);
const query = formData.get("query");
alert(`You searched for '${query}'`);
}
return (
<form onSubmit={handleSubmit}>
<input name="query" />
<button type="submit">Search</button>
</form>
);
}Reading form data with onSubmit works in every version of React and gives you direct access to the submit event, so you can call e.preventDefault() and read the data yourself. Passing the function to the action prop instead runs the submission in a Transition. React then tracks the pending state, sends thrown errors to the nearest error boundary, and lets the form work with useActionState and useOptimistic. An action can also be a Server Function, which onSubmit does not support.
Pass a function to the action prop of form to run the function when the form is submitted. formData will be passed to the function as an argument so you can access the data submitted by the form. This differs from the conventional HTML action, which only accepts URLs. Unlike onSubmit, an action runs in a Transition and calling e.preventDefault() isn't needed. After the action function succeeds, all uncontrolled field elements in the form are reset.
152a471aa9ac2f6f0f3e64c04f39da790d40cf61
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>
);
}Manipular envio de formulário com uma Server Function {/handle-form-submission-with-a-server-function/}
Renderize um <form> com um input e um botão de envio. Passe uma Server Function (uma função marcada com 'use server') para a prop action do formulário para executar a função quando o formulário for enviado.
Passar uma Server Function para <form action> permite que os usuários enviem formulários sem o JavaScript ativado ou antes que o código seja carregado. Isso é benéfico para usuários que têm uma conexão lenta, dispositivo ou têm o JavaScript desativado e é semelhante à maneira como os formulários funcionam quando uma URL é passada para a prop action.
Você pode usar campos de formulário ocultos para fornecer dados para a ação do <form>. A Server Function será chamada com os dados do campo de formulário oculto como uma instância de 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>
);
}Em vez de usar campos de formulário ocultos para fornecer dados à ação do <form>, você pode chamar o método bind para fornecer argumentos extras. Isso vinculará um novo argumento (productId) à função, além do formData que é passado como argumento para a função.
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>
);
}Quando o <form> é renderizado por um Server Component, e uma Server Function é passada para a prop action do <form>, o formulário é progressivamente aprimorado.
Exibir um estado pendente durante o envio do formulário {/display-a-pending-state-during-form-submission/}
Para exibir um estado pendente quando um formulário está sendo enviado, você pode chamar o Hook useFormStatus em um componente renderizado em um <form> e ler a propriedade pending retornada.
Aqui, usamos a propriedade pending para indicar que o formulário está sendo enviado.
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} />;
}export async function submitForm(query) {
await new Promise((res) => setTimeout(res, 1000));
}Para saber mais sobre o Hook useFormStatus, consulte a documentação de referência.
O Hook useOptimistic fornece uma maneira de atualizar otimistamente a interface do usuário antes que uma operação em segundo plano, como uma solicitação de rede, seja concluída. No contexto de formulários, essa técnica ajuda a tornar os aplicativos mais responsivos. Quando um usuário envia um formulário, em vez de esperar pela resposta do servidor para refletir as alterações, a interface é imediatamente atualizada com o resultado esperado.
Por exemplo, quando um usuário digita uma mensagem no formulário e pressiona o botão "Enviar", o Hook useOptimistic permite que a mensagem apareça imediatamente na lista com um rótulo "Enviando...", mesmo antes que a mensagem seja realmente enviada para um servidor. Essa abordagem "otimista" dá a impressão de velocidade e responsividade. O formulário então tenta enviar a mensagem de verdade em segundo plano. Depois que o servidor confirma que a mensagem foi recebida, o rótulo "Enviando..." é removido.
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} />;
}export async function deliverMessage(message) {
await new Promise((res) => setTimeout(res, 1000));
return message;
}Em alguns casos, a função chamada pela prop action de um <form> lança um erro. Você pode tratar esses erros envolvendo o <form> em um Error Boundary. Se a função chamada pela prop action de um <form> lançar um erro, o fallback para o error boundary será exibido.
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>
);
}{
"dependencies": {
"react": "19.0.0-rc-3edc000d-20240926",
"react-dom": "19.0.0-rc-3edc000d-20240926",
"react-scripts": "^5.0.0",
"react-error-boundary": "4.0.3"
},
"main": "/index.js",
"devDependencies": {}
}Exibir um erro de envio de formulário sem JavaScript {/display-a-form-submission-error-without-javascript/}
Exibir uma mensagem de erro de envio de formulário antes que o bundle JavaScript seja carregado para aprimoramento progressivo exige que:
<form>seja renderizado por um Client Component- a função passada para a prop
actiondo<form>seja uma Server Function - o Hook
useActionStateseja usado para exibir a mensagem de erro
useActionState recebe dois parâmetros: um Server Function e um estado inicial. useActionState retorna dois valores, uma variável de estado e uma ação. A ação retornada por useActionState deve ser passada para a prop action do formulário. A variável de estado retornada por useActionState pode ser usada para exibir uma mensagem de erro. O valor retornado pela Server Function passada para useActionState será usado para atualizar a variável de estado.
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>
</>
);
}let emails = [];
export async function signUpNewUser(newEmail) {
if (emails.includes(newEmail)) {
throw new Error("This email address has already been added");
}
emails.push(newEmail);
}Saiba mais sobre como atualizar o estado de uma ação de formulário com a documentação useActionState
Os formulários podem ser projetados para lidar com várias ações de envio com base no botão pressionado pelo usuário. Cada botão dentro de um formulário pode ser associado a uma ação ou comportamento distinto definindo a prop formAction.
Quando um usuário toca em um botão específico, o formulário é enviado e uma ação correspondente, definida pelos atributos e ação daquele botão, é executada. Por exemplo, um formulário pode, por padrão, enviar um artigo para revisão, mas ter um botão separado com o formAction definido para salvar o artigo como um rascunho.
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>
);
}