Server Actions
In Next.js, you can use Server Actions to fetch and mutate data on the server side without the need for an API route Next.js will do that under the hood for you. Server Actions are built on top of React Actions and provide a convenient way to fetch data and perform server-side mutations, reduce client-side JavaScript, and enhance forms progressively.
Convention
To enable Server Actions in your Next.js project, you need to set the serverActions
flag in your next.config.js
file:
module.exports = {
experimental: {
serverActions: true,
},
}
Creating Server Actions
You can define Server Actions in two ways:
- Inside a server component.
- In a separate file (for Client and Server components), for re-usability. You can also define multiple Server Actions in a single file.
With Server Components
To create a Server Action within a Server Component, define an asynchronous function with the 'use server'
directive at the top of the function body.
export default function ServerComponent() {
async function myAction() {
'use server'
// ...
}
}
With Client Components
If you want to use a Server Action inside a Client Component, create the action in a separate file with the 'use server'
directive at the top of the file. Then, import the Server Action into your Client Component.
// app/actions.js
'use server'
export async function myAction() {
// ...
}
// app/client-component.jsx
'use client'
import { myAction } from './actions';
export default function ClientComponent() {
return (
<form action={myAction}>
<button type="submit">Add to Cart</button>
</form>
);
}
Invoking Server Actions in Client components
Let's briefly gloss over a quick preview of how you can invoke server actions in client components using the following methods. We'll cover the details of data mutations with server actions in mutations (opens in a new tab).
Using the action
prop
React's action
prop allows you to invoke a Server Action on a <form>
element. Here's an example:
export default function AddToCart({ productId }) {
async function addItem(data) {
'use server'
// ...
}
return (
<form action={addItem}>
<button type="submit">Add to Cart</button>
</form>
)
}
When the form is submitted, the Server Action specified in the action
prop will be triggered.
When the specified element is interacted with (e.g., clicked), the associated Server Action (myAction
in this case) will be invoked.
Custom Invocation with startTransition
If you prefer to invoke Server Actions without relying on the action
or formAction
props, you can use startTransition
to trigger the action explicitly. This method allows you to disable Progressive Enhancement. Here's an example:
'use client'
import { useTransition } from 'react'
import { addItem } from '../actions'
function ExampleClientComponent({ id }: { id: string }) {
let [isPending, startTransition] = useTransition()
return (
<button onClick={() => startTransition(() => addItem(id))}>
Add To Cart
</button>
)
}
In this approach, when the button is clicked, the startTransition
function is called, which wraps the invocation of the Server Action (myAction
in this case) and any additional logic or state updates you may want to perform.