Skip to content

Commit 8bce77f

Browse files
committed
Enhance form documentation by expanding on the use of Server Functions in the action prop, including detailed examples for passing extra data and handling form submissions. Clarify the behavior of form elements and their interaction with FormData.
1 parent 9d5629b commit 8bce77f

1 file changed

Lines changed: 90 additions & 9 deletions

File tree

  • src/content/reference/react-dom/components

‎src/content/reference/react-dom/components/form.md‎

Lines changed: 90 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -128,20 +128,57 @@ export default function Search() {
128128

129129
### Handling form submission with a Server Function {/*handle-form-submission-with-a-server-function*/}
130130

131-
Render a `<form>` with an input and submit button. Pass a Server Function (a function marked with [`'use server'`](/reference/rsc/use-server)) to the form's `action` prop to run the function when the form is submitted.
131+
A `<form>`'s `action` prop can run a Server Function (a function marked with [`'use server'`](/reference/rsc/use-server)) when the user submits the form. Users can submit that form before JavaScript loads, and when JavaScript is disabled. This matches how forms behave when you pass a URL to `action`.
132132

133-
Passing a Server Function to a form's `action` prop allows users to submit the form before JavaScript loads or when JavaScript is disabled. This matches how forms behave when you pass a URL to `action`.
133+
React calls the Server Function with the form's [`FormData`](https://developer.mozilla.org/en-US/docs/Web/API/FormData) and includes every input with a `name` attribute. To pass additional data, such as an ID from props, see [Passing extra data to an Action](#passing-extra-data-to-an-action).
134134

135-
You can use hidden form fields to pass data to the Server Function. React includes the hidden field values in the [`FormData`](https://developer.mozilla.org/en-US/docs/Web/API/FormData) passed to the function.
135+
```jsx
136+
import { addComment } from './actions.js';
137+
138+
function CommentForm() {
139+
return (
140+
<form action={addComment}>
141+
<textarea name="comment" />
142+
<button type="submit">Comment</button>
143+
</form>
144+
);
145+
}
146+
```
147+
148+
```js
149+
// actions.js
150+
'use server';
151+
152+
export async function addComment(formData) {
153+
const comment = formData.get('comment');
154+
// ...
155+
}
156+
```
157+
158+
<DeepDive>
159+
160+
#### Passing extra data to an Action {/*passing-extra-data-to-an-action*/}
161+
162+
An Action receives the submitted [`FormData`](https://developer.mozilla.org/en-US/docs/Web/API/FormData). To include data the user did not enter, such as an ID from props, use one of these approaches:
163+
164+
* **Hidden fields** add the value to `FormData`. The value appears in the HTML, and `formData.get` returns a string. Users can submit the form before JavaScript loads.
165+
* **Binding with `bind`** passes the value as an argument to a Server Function, before `formData`. The argument keeps its type, so a number stays a number. It must be [serializable](/reference/rsc/use-server#serializable-parameters-and-return-values). Users can submit the form before JavaScript loads.
166+
* **A function in the component** reads props and state directly. It runs after JavaScript loads, then calls a Server Function with those values.
167+
168+
The client sends hidden field values and bound arguments. Check on the server that the logged-in user is allowed to perform the Action. See [Security considerations](/reference/rsc/use-server#security).
169+
170+
#### Hidden fields {/*passing-extra-data-hidden-fields*/}
171+
172+
In a Server Component, render an `<input type="hidden">` with a `name` and `value`. React includes that value in the `FormData` passed to the Action.
136173

137174
```jsx
175+
// Server Component
138176
import { updateCart } from './lib.js';
139177

140-
function AddToCart({productId}) {
178+
function AddToCart({ productId }) {
141179
async function addToCart(formData) {
142180
'use server';
143-
const productId = formData.get('productId');
144-
await updateCart(productId);
181+
await updateCart(formData.get('productId'));
145182
}
146183
return (
147184
<form action={addToCart}>
@@ -152,12 +189,17 @@ function AddToCart({productId}) {
152189
}
153190
```
154191

155-
Instead of using a hidden form field, call the <CodeStep step={1}>`bind`</CodeStep> method to pass an extra argument to the Server Function. This binds <CodeStep step={2}>`productId`</CodeStep> as an argument before the <CodeStep step={3}>`formData`</CodeStep> that React passes to the function.
192+
React includes a submit button's `name` and `value` in `FormData` when that button submits the form.
193+
194+
#### Binding with `bind` {/*passing-extra-data-bind*/}
156195

157-
```jsx [[1, 8, "bind"], [2,8, "productId"], [2,4, "productId"], [3,4, "formData"]]
196+
In a Server Component, call [`bind`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind) on the Server Function and pass the bound function to `action`. Pass `null` as the first argument to `bind`. Each argument after `null` comes before the `formData` argument React passes when the form is submitted.
197+
198+
```jsx
199+
// Server Component
158200
import { updateCart } from './lib.js';
159201

160-
function AddToCart({productId}) {
202+
function AddToCart({ productId }) {
161203
async function addToCart(productId, formData) {
162204
'use server';
163205
await updateCart(productId);
@@ -171,6 +213,45 @@ function AddToCart({productId}) {
171213
}
172214
```
173215

216+
`addToCart.bind(null, productId)` calls `addToCart(productId, formData)`.
217+
218+
[`useActionState`](/reference/react/useActionState) passes the previous state before `FormData`. Bound arguments come first, so the Server Function receives the bound values, the previous state, and then `formData`. Define that function in a separate file and bind it from the Client Component.
219+
220+
#### A function in the component {/*passing-extra-data-function*/}
221+
222+
Define the function you pass to `action` in the Client Component that has the props or state. That function reads those values and passes them to a Server Function.
223+
224+
```jsx
225+
// AddToCart.js
226+
'use client';
227+
228+
import { updateCart } from './actions.js';
229+
230+
function AddToCart({ productId }) {
231+
async function addToCart(formData) {
232+
await updateCart(productId, formData);
233+
}
234+
return (
235+
<form action={addToCart}>
236+
<button type="submit">Add to Cart</button>
237+
</form>
238+
);
239+
}
240+
```
241+
242+
```js
243+
// actions.js
244+
'use server';
245+
246+
export async function updateCart(productId, formData) {
247+
// ...
248+
}
249+
```
250+
251+
Users can submit this form only after JavaScript loads.
252+
253+
</DeepDive>
254+
174255
---
175256

176257
### Displaying a pending state during form submission {/*display-a-pending-state-during-form-submission*/}

0 commit comments

Comments
 (0)