React Server Components
'use server'
is for use withusing React Server Components.
'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 call these functionsServer Functions.
asyncfunctionaddToCart(data){
'use server';
// ...
}
When calling a Server Function on the client, it will make a network request to the server that includes a serialized copy of any arguments passed. If the Server Function 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 Functions that can be used anywhere, including imported in client code.
Caveats
'use server'
must be at the very beginning of their function or module; above any other code including imports (comments above directives are OK). They must be written with single or double quotes, not backticks.'use server'
can only be used in server-side files. The resulting Server Functions can be passed to Client Components through props. See supportedtypes for serialization.- To import a Server Functions fromclient code, the directive must be used on a module level.
- Because the underlying network calls are always asynchronous,
'use server'
can only be used on async functions. - Always treat arguments to Server Functions as untrusted input and authorize any mutations. Seesecurity considerations.
- Server Functions should be called in aTransition. Server Functions passed to
<form action>
orformAction
will automatically be called in a transition. - Server Functions are designed for mutations that update server-side state; they are not recommended for data fetching. Accordingly, frameworks implementing Server Functions typically process one action at a time and do not have a way to cache the return value.
Security considerations
Arguments to Server Functions are fully client-controlled. For security, always treat them as untrusted input, and make sure to validate and escape arguments as appropriate.
In any Server Function, make sure to validate that the logged-in user is allowed to perform that action.
Under Construction
To prevent sending sensitive data from a Server Function, there are experimental taint APIs to prevent unique values and objects from being passed to client code.
Seeexperimental_taintUniqueValue andexperimental_taintObjectReference.
Serializable arguments and return values
Since client code calls the Server Function over the network, any arguments passed will need to be serializable.
Here are supported types for Server Function arguments:
- Primitives
- Iterables containing serializable values
- Date
- FormData instances
- Plainobjects: those created withobject initializers, with serializable properties
- Functions that are Server Functions
- Promises
Notably, these are not supported:
- React elements, orJSX
- Functions, including component functions or any other function that is not a Server Function
- Classes
- Objects that are instances of any class (other than the built-ins mentioned) or objects witha null prototype
- Symbols not registered globally, ex.
Symbol('my new symbol')
- Events from event handlers
Supported serializable return values are the same asserializable props for a boundary Client Component.
Usage
Server Functions in forms
The most common use case of Server Functions will be calling functions that mutate data. On the browser, theHTML form element is the traditional approach for a user to submit a mutation. With React Server Components, React introduces first-class support for Server Functions as Actions informs.
Here is a form that allows a user to request a username.
// App.js
asyncfunctionrequestUsername(formData){
'use server';
constusername =formData.get('username');
// ...
}
exportdefaultfunctionApp(){
return(
<formaction={requestUsername}>
<inputtype="text"name="username"/>
<buttontype="submit">Request</button>
</form>
);
}
In this examplerequestUsername
is a Server Function passed to a<form>
. When a user submits this form, there is a network request to the server functionrequestUsername
. When calling a Server Function in a form, React will supply the form’sFormData as the first argument to the Server Function.
By passing a Server Function to the formaction
, React canprogressively enhance the form. This means that forms can be submitted before the JavaScript bundle is loaded.
Handling return values in forms
In the username request form, there might be the chance that a username is not available.requestUsername
should tell us if it fails or not.
To update the UI based on the result of a Server Function while supporting progressive enhancement, useuseActionState
.
// requestUsername.js
'use server';
exportdefaultasyncfunctionrequestUsername(formData){
constusername =formData.get('username');
if(canRequest(username)){
// ...
return'successful';
}
return'failed';
}
// UsernameForm.js
'use client';
import{useActionState}from'react';
importrequestUsernamefrom'./requestUsername';
functionUsernameForm(){
const[state,action] =useActionState(requestUsername,null,'n/a');
return(
<>
<formaction={action}>
<inputtype="text"name="username"/>
<buttontype="submit">Request</button>
</form>
<p>Last submission request returned:{state}</p>
</>
);
}
Note that like most Hooks,useActionState
can only be called inclient code.
Calling a Server Function outside of<form>
Server Functions are exposed server endpoints and can be called anywhere in client code.
When using a Server Function outside aform, call the Server Function in aTransition, which allows you to display a loading indicator, showoptimistic state updates, and handle unexpected errors. Forms will automatically wrap Server Functions in transitions.
importincrementLikefrom'./actions';
import{useState,useTransition}from'react';
functionLikeButton(){
const[isPending,startTransition] =useTransition();
const[likeCount,setLikeCount] =useState(0);
constonClick =()=>{
startTransition(async()=>{
constcurrentCount =awaitincrementLike();
setLikeCount(currentCount);
});
};
return(
<>
<p>Total Likes:{likeCount}</p>
<buttononClick={onClick}disabled={isPending}>Like</button>;
</>
);
}
// actions.js
'use server';
letlikeCount =0;
exportdefaultasyncfunctionincrementLike(){
likeCount++;
returnlikeCount;
}
To read a Server Function return value, you’ll need toawait
the promise returned.