'use server'
'use server'
marks server-side functions that can be called from client-side code.
Reference
'use server'
Add 'use server'
at the top of an async function body to mark the function as callable by the client. We refer to server functions that have been marked with 'use server'
as server actions.
async function addToCart(data) {
'use server';
// ...
}
As a server action, you can pass addToCart
as a prop to a Client Component to be invoked on the client.
When calling a server action on the client, it will make a network request to the server that includes a serialized copy of any arguments passed. If the server action returns a value, that value will be serialized and returned to the client.
Instead of individually marking functions with 'use server'
, you can add the directive to the top of a file to mark all exports within that file as server actions.
Serializable arguments and return values
As client code calls the server action over the network, any arguments passed will need to be serializable.
Here are supported types for server action arguments:
- Primitives
- Iterables
- FormData instances
- Plain objects, those created with object initializers, with serializable properties
- Functions that are server actions
- Promises
Notably, these are not supported:
- React Elements, or JSX
- Functions, this includes component functions or any other function that is not a server action
- Classes
- Objects that are not an instance of Object, or are null-prototype objects
- Symbols not registered globally, ex.
Symbol('my new symbol')
Supported serializable return values are the same as serializable props for a boundary Client Component.
Security considerations
Recall that parameters to server actions are fully client-controlled. For security, always treat them as untrusted input, and make sure to validate and escape arguments as appropriate.
In addition, we recommend validating user authorization for any server mutations a server action may perform.
Caveats
'use server'
can only be used in server-side files; the resulting functions can be passed to Client Components through props.- Because the underlying network calls are always asynchronous,
'use server'
can be used only on async functions. - server actions must be called in . When used in a
<form action>
, form will ensure the server action is called in a transition. Elsewhere, you will need to manually call a server action in a transition. - Directives like
'use server'
must be at the very beginning of their function or file, above any other code including imports (comments above directives are OK). They must be written with single or double quotes, not backticks.
Usage
Server actions in forms
The most common use case of server actions will be calling server functions that mutate data. On the browser, the HTML form element is the traditional approach for a user to submit a mutation. With React Server Components, React introduces first-class support for server actions in forms.
Here is a form that allows a user to request a username.
// UsernameForm.js
'use client';
export default UsernameForm({submit}) {
return (
<form action={submit}>
<input type="text" name="username" />
<button type="submit">Request</button>
</form>
);
}
// App.js
import UsernameForm from './UsernameForm';
function requestUsername(formData) {
'use server';
const username = formData.get('username');
// ...
}
export default App() {
<UsernameForm submit={requestUsername}>
}
In this example UsernameForm
is a Client Component and receives a server action as the prop submit
. When a user submits this form, there is a network request to the server function requestUsername
.
When calling a server action in a <form action>
, React will supply the form’s FormData as the first argument to the server action.
Progressive Enhancement in <form>
In the above example, the <form>
is rendered in a Client Component. By instead rendering the <form>
in a Server Component, React can support progressively enhanced forms.
In this context, we mean that server-rendered forms can provide the baseline experience of submitting a form without JavaScript. This is useful for apps that are server-side rendered (SSR) where HTML scaffolding is sent to the client first, before any code is downloaded to add interactivity.
Deep Dive
Server-side rendering and React Server Components are two features for optimizing performance of React apps and can complement one another.
Server-side rendering (SSR) is the concept of taking a single render pass of a React app to resolve it to its base UI primitives, HTML elements for the web. This HTML is sent down to the client to serve as “scaffolding” while JavaScript is still being downloaded and evaluated.
SRR is an optimization for “time to paint” but it still requires all your app code to download and be evaluated on the client. The client then needs to hydrate this scaffolding to add interactivity.
React Server Components (RSC) is the concept of breaking up your React module dependency tree to determine what components can be rendered on the server and what can be sent to the client. In contrast to SSR, components that are rendered on the server have access to server APIs and can make data-fetches.
These rendered Server Components are streamed down to the client in a special encoding to be translated to HTML or whatever client UI primitive. There is no hydration due to limitations of Server Components.
RSC is an optimization for “time to interactive” as it reduces the code that needs to be downloaded and run by the client.
Here is the same username request form but rendered as a Server Component.
// App.js
export default App() {
function requestUsername(formData) {
'use server';
const username = formData.get('username');
// ...
}
return (
<form action={requestUsername}>
<input type="text" name="username" />
<button type="submit">Request</button>
</form>
);
}
The <form>
is rendered in a Server Component but the form submission will take place on the client. Before hydration or if JavaScript is disabled, this form will still allow users to call the server action.
Handling return values
You’ll notice that in a username request form, there might be the chance that a username is not available. requestUsername
should tell us if it fails or not. How does the form receive the return value of the server action?
Here is where you can use useFormState
, a hook designed for receiving a server action return value that supports progressive enhancement.
// App.js
import {useFormState} from 'react';
export default App() {
function requestUsername(formData) {
'use server';
const username = formData.get('username');
if (canRequest(username)) {
// ...
return 'successful';
}
return 'failed';
}
const [returnValue, action] = useFormState(requestUsername, 'n/a');
return (
<>
<form action={requestUsername}>
<input type="text" name="username" />
<button type="submit">Request</button>
</form>
<p>Last submission request returned: {returnValue}</p>
</>
);
}
Calling a server action outside of <form>
Server actions are exposed server endpoints to client code and can in theory be called anywhere in client code.
import incrementLike from './actions';
import {useState, useTransition} from 'react';
function LikeButton() {
const [pending, startTransition] = useTransition();
const [likeCount, setLikeCount] = useState(0);
const onClick = () => startTransition(async () => {
const currentCount = await incrementLike();
setLikeCount(currentCount);
});
return (
<>
<p>Total Likes: {likeCount}</p>
<button onClick={onClick} disabled={pending}>Like</button>;
</>
);
}
If you call a server action outside of a form, which has first-class support for server actions, you can only do so in a Client Component, which lacks progressive enhancement. In addition, you’ll need to manually call the server action in a transition <form action>
takes care of this for you.
To read a server action return value, you’ll need to await
the promise returned.