Skip to content

Commit 47539b0

Browse files
authored
Fix Server Functions documentation examples
1 parent 6be2b02 commit 47539b0

1 file changed

Lines changed: 59 additions & 31 deletions

File tree

src/content/reference/rsc/server-functions.md

Lines changed: 59 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -42,33 +42,30 @@ Server Components can define Server Functions with the `"use server"` directive:
4242
// Server Component
4343
import Button from './Button';
4444

45-
function EmptyNote () {
45+
function EmptyNote() {
4646
async function createNoteAction() {
4747
// Server Function
4848
'use server';
4949

5050
await db.notes.create();
5151
}
5252

53-
return <Button onClick={createNoteAction}/>;
53+
return <Button onClick={createNoteAction} />;
5454
}
5555
```
5656

5757
When React renders the `EmptyNote` Server Component, it will create a reference to the `createNoteAction` function, and pass that reference to the `Button` Client Component. When the button is clicked, React will send a request to the server to execute the `createNoteAction` function with the reference provided:
5858

59-
```js {5}
59+
```js {4}
6060
"use client";
6161

6262
export default function Button({onClick}) {
63-
console.log(onClick);
64-
// {$$typeof: Symbol.for("react.server.reference"), $$id: 'createNoteAction'}
65-
return <button onClick={() => onClick()}>Create Empty Note</button>
63+
return <button onClick={() => onClick()}>Create Empty Note</button>;
6664
}
6765
```
6866

6967
For more, see the docs for [`"use server"`](/reference/rsc/use-server).
7068

71-
7269
### Importing Server Functions from Client Components {/*importing-server-functions-from-client-components*/}
7370

7471
Client Components can import Server Functions from files that use the `"use server"` directive:
@@ -79,19 +76,17 @@ Client Components can import Server Functions from files that use the `"use serv
7976
export async function createNote() {
8077
await db.notes.create();
8178
}
82-
8379
```
8480

8581
When the bundler builds the `EmptyNote` Client Component, it will create a reference to the `createNote` function in the bundle. When the `button` is clicked, React will send a request to the server to execute the `createNote` function using the reference provided:
8682

87-
```js [[1, 2, "createNote"], [1, 5, "createNote"], [1, 7, "createNote"]]
83+
```js [[1, 3, "createNote"], [1, 6, "createNote"]]
8884
"use client";
85+
8986
import {createNote} from './actions';
9087

9188
function EmptyNote() {
92-
console.log(createNote);
93-
// {$$typeof: Symbol.for("react.server.reference"), $$id: 'createNote'}
94-
<button onClick={() => createNote()} />
89+
return <button onClick={() => createNote()}>Create Empty Note</button>;
9590
}
9691
```
9792

@@ -109,12 +104,14 @@ export async function updateName(name) {
109104
return {error: 'Name is required'};
110105
}
111106
await db.users.updateName(name);
107+
return {error: null};
112108
}
113109
```
114110

115-
```js [[1, 3, "updateName"], [1, 13, "updateName"], [2, 11, "submitAction"], [2, 25, "submitAction"]]
111+
```js [[1, 4, "updateName"], [1, 14, "updateName"], [2, 12, "submitAction"], [2, 26, "submitAction"]]
116112
"use client";
117113

114+
import {useState, useTransition} from 'react';
118115
import {updateName} from './actions';
119116

120117
function UpdateName() {
@@ -123,38 +120,54 @@ function UpdateName() {
123120

124121
const [isPending, startTransition] = useTransition();
125122

126-
const submitAction = async () => {
123+
function submitAction() {
127124
startTransition(async () => {
128125
const {error} = await updateName(name);
129126
startTransition(() => {
130-
if (error) {
131-
setError(error);
132-
} else {
127+
setError(error);
128+
if (!error) {
133129
setName('');
134130
}
135131
});
136-
})
132+
});
137133
}
138134

139135
return (
140136
<form action={submitAction}>
141-
<input type="text" name="name" disabled={isPending}/>
137+
<input
138+
type="text"
139+
name="name"
140+
value={name}
141+
onChange={event => setName(event.target.value)}
142+
disabled={isPending}
143+
/>
142144
{error && <span>Failed: {error}</span>}
143145
</form>
144-
)
146+
);
145147
}
146148
```
147149

148150
This allows you to access the `isPending` state of the Server Function by wrapping it in an Action on the client.
149151

150-
For more, see the docs for [Calling a Server Function outside of `<form>`](/reference/rsc/use-server#calling-a-server-function-outside-of-form)
152+
For more, see the docs for [Calling a Server Function outside of `<form>`](/reference/rsc/use-server#calling-a-server-function-outside-of-form).
151153

152154
### Server Functions with Form Actions {/*using-server-functions-with-form-actions*/}
153155

154156
Server Functions work with the new Form features in React 19.
155157

156-
You can pass a Server Function to a Form to automatically submit the form to the server:
158+
You can pass a Server Function to a Form to automatically submit the form to the server. React passes the submitted `FormData` to the Server Function as its first argument:
157159

160+
```js [[1, 3, "updateName"]]
161+
"use server";
162+
163+
export async function updateName(formData) {
164+
const name = formData.get('name');
165+
if (typeof name !== 'string' || !name) {
166+
throw new Error('Name is required');
167+
}
168+
await db.users.updateName(name);
169+
}
170+
```
158171

159172
```js [[1, 3, "updateName"], [1, 7, "updateName"]]
160173
"use client";
@@ -166,50 +179,65 @@ function UpdateName() {
166179
<form action={updateName}>
167180
<input type="text" name="name" />
168181
</form>
169-
)
182+
);
170183
}
171184
```
172185

173-
When the Form submission succeeds, React will automatically reset the form. You can add `useActionState` to access the pending state, last response, or to support progressive enhancement.
186+
When the Form submission succeeds, React will automatically reset the uncontrolled fields in the form. Server Function forms can be submitted before the JavaScript bundle loads. You can add `useActionState` to access the pending state and last response.
174187

175188
For more, see the docs for [Server Functions in Forms](/reference/rsc/use-server#server-functions-in-forms).
176189

177190
### Server Functions with `useActionState` {/*server-functions-with-use-action-state*/}
178191

179-
You can call Server Functions with `useActionState` for the common case where you just need access to the action pending state and last returned response:
192+
You can call Server Functions with `useActionState` for the common case where you just need access to the action pending state and last returned response. The Server Function receives the previous state as its first argument and the submitted `FormData` as its second argument. Its return value becomes the next state:
193+
194+
```js [[1, 3, "updateName"]]
195+
"use server";
196+
197+
export async function updateName(previousState, formData) {
198+
const name = formData.get('name');
199+
if (typeof name !== 'string' || !name) {
200+
return {error: 'Name is required'};
201+
}
202+
await db.users.updateName(name);
203+
return {error: null};
204+
}
205+
```
180206

181-
```js [[1, 3, "updateName"], [1, 6, "updateName"], [2, 6, "submitAction"], [2, 9, "submitAction"]]
207+
```js [[1, 4, "updateName"], [1, 7, "updateName"], [2, 7, "submitAction"], [2, 10, "submitAction"]]
182208
"use client";
183209

210+
import {useActionState} from 'react';
184211
import {updateName} from './actions';
185212

186213
function UpdateName() {
187214
const [state, submitAction, isPending] = useActionState(updateName, {error: null});
188215

189216
return (
190217
<form action={submitAction}>
191-
<input type="text" name="name" disabled={isPending}/>
218+
<input type="text" name="name" disabled={isPending} />
192219
{state.error && <span>Failed: {state.error}</span>}
193220
</form>
194221
);
195222
}
196223
```
197224

198-
When using `useActionState` with Server Functions, React will also automatically replay form submissions entered before hydration finishes. This means users can interact with your app even before the app has hydrated.
225+
When using `useActionState` with a Server Function, the form can be submitted before hydration finishes and the Server Function's response can be shown before the app has hydrated.
199226

200227
For more, see the docs for [`useActionState`](/reference/react/useActionState).
201228

202229
### Progressive enhancement with `useActionState` {/*progressive-enhancement-with-useactionstate*/}
203230

204231
Server Functions also support progressive enhancement with the third argument of `useActionState`.
205232

206-
```js [[1, 3, "updateName"], [1, 6, "updateName"], [2, 6, "/name/update"], [3, 6, "submitAction"], [3, 9, "submitAction"]]
233+
```js [[1, 4, "updateName"], [1, 7, "updateName"], [2, 7, "/name/update"], [3, 7, "submitAction"], [3, 10, "submitAction"]]
207234
"use client";
208235

236+
import {useActionState} from 'react';
209237
import {updateName} from './actions';
210238

211239
function UpdateName() {
212-
const [, submitAction] = useActionState(updateName, null, `/name/update`);
240+
const [, submitAction] = useActionState(updateName, {error: null}, `/name/update`);
213241

214242
return (
215243
<form action={submitAction}>
@@ -219,6 +247,6 @@ function UpdateName() {
219247
}
220248
```
221249

222-
When the <CodeStep step={2}>permalink</CodeStep> is provided to `useActionState`, React will redirect to the provided URL if the form is submitted before the JavaScript bundle loads.
250+
When the <CodeStep step={2}>permalink</CodeStep> is provided to `useActionState`, the browser will navigate to the provided URL if the form is submitted before the JavaScript bundle loads. The same form component, including the same Server Function and permalink, must be rendered at the destination so React can pass the returned state to it.
223251

224252
For more, see the docs for [`useActionState`](/reference/react/useActionState).

0 commit comments

Comments
 (0)