Next.js Server Actions are a powerful feature that allows you to create server-side rendered (SSR) pages with dynamic content. This means you can generate pages on the fly based on user input or data.
To get started with Next.js Server Actions, you'll need to create a new API route using the `pages/api` directory. This is where you'll define your server-side logic.
Next.js Server Actions use the `getServerSideProps` method to fetch data on the server before rendering the page. This method is called when the page is requested, allowing you to fetch data and pass it to the page as props.
By using `getServerSideProps`, you can create pages that render quickly and efficiently, even when dealing with complex data.
Defining Components
Server components are defined using the `use server` directive, which marks an async function as a Server Action. This directive is placed at the top of the function body.
You can create server components in a separate file, where you place the `use server` directive at the top of the file, even before imports. This informs Next.js that the file includes server actions.
In server components, you define Server Actions using the `use server` directive. This directive is also used to mark functions as server actions in separate files.
Server components can use the inline function level or module level `use server` directive. To inline a server action, add `use server` to the top of the function body.
To use server actions in Next.js server components, create an async function with the `use server` directive. You must place the directive on top of the function body.
Server Actions Basics
Server Actions can be invoked from any HTML element, such as a button, input type="submit", or form.
You can use the action prop to invoke a Server Action from an HTML element, like a button or form. For example, the code to invoke the createComment Server Action when the user clicks the button is straightforward.
Server Actions can also be invoked from event handlers, which gives you a lot of flexibility. This means you can use them in various situations, not just from HTML elements.
The action prop is not limited to HTML elements, and can be used in event handlers, useEffect, and third-party libraries. This opens up a wide range of possibilities for using Server Actions in your Next.js application.
You can also invoke a Server Action from a form using the useFormState hook. This is a useful method for handling form submissions and Server Actions in one go.
The startTransition hook is another way to invoke a Server Action from any component in your Next.js application. This gives you even more flexibility and options for using Server Actions in your code.
Request and Response
The request and response payloads are structured in a way that's easy to understand. The payload of a POST request includes unique identifiers and values for each form field, which is essential for Server Actions to correctly map and process the incoming data.
The payload structure is as follows:
- 1_$ACTION_ID... represents a unique identifier for the Server Action being invoked.
- 1_name and 1_message are the form fields, where the numeric prefix and underscore signify their association with the action and the subsequent data represents the user input.
Upon successful execution of the Server Action, the server responds with a payload that includes a status indicator and an acknowledgment of the action's completion. The status indicator provides context about the execution environment and result.
Request Payload Structure
The request payload structure in Next.js is quite fascinating. It's designed to include unique identifiers and values for each form field, which is essential for Server Actions to correctly map and process the incoming data.
This structuring is handled automatically by Next.js, making it a great feature for developers.
Let's take a closer look at the payload structure. In the example provided, the payload includes a unique identifier for the Server Action being invoked, represented by 1_$ACTION_ID... This ensures that the server can accurately identify and execute the corresponding action function.
The payload also includes form fields, such as 1_name and 1_message, which are associated with the action and user input, respectively. The numeric prefix and underscore signify their association with the action and the subsequent data represents the user input.
Here's a breakdown of the payload structure:
- Unique identifier for the Server Action: 1_$ACTION_ID...
- Form fields: 1_name and 1_message
This structured payload is crucial for Server Actions to function correctly, and Next.js handles it automatically, making development easier and more efficient.
Loading State
You can use the useFormStatus hook to display a loading state while a form is being submitted.
The useFormStatus hook can only live in a client component and can only be used as a child of a form element using a Server Action.
This hook will reflect the new status in the variable pending and adjust the button component accordingly.
As the form is submitted, the loading state will be displayed, providing visual feedback to the user and creating a better user experience.
You can expand this code to provide more visual feedback to the user and create a better user experience.
The useFormStatus hook is a powerful tool for managing the loading state of a form, making it easier to create a seamless user experience.
Next.js Server Actions
Next.js Server Actions are a powerful feature that allows you to perform server-side logic directly in your client-side code. They were introduced in Next.js version 13, but became stable and incorporated by default in version 14.
Server Actions can be used for various use cases, including fetching data from external APIs, performing business logic, and updating your database. They can also handle form submissions and API routes.
Here are some key differences between Server Actions and conventional API routes: FeatureServer ActionsAPI RoutesTriggeringCan be triggered from client-side codeRequire a separate API callServer-side logicCan be executed on the server-sideMust be executed on the client-side
Server Actions can be created using the App Router or the Pages Router, and can be used to perform complex server-side logic in a simple and efficient way.
Understanding Next.js
Next.js Server Actions are a powerful feature that has been part of the framework since version 13, but they're now stable and incorporated by default as a framework feature in version 14.
Server Actions are well-suited for a variety of use cases, including fetching data from external APIs, performing business logic, and updating your database.
Here are some specific use cases for Server Actions:
- Feching data from external APIs
- Performing business logic
- Updating your database
To get started with Server Actions, you'll need to create a new API route in the pages/api directory, and define the Server Action as an async function in a new file called action.js.
Here's an example of how to define a Server Action:
```javascript
export async function action() {
// server-side logic here
}
```
You can also use the App Router to create a new API route, by creating a new folder called api and a new file called [action].js.
Server Actions can be triggered from a form submission, and can expect parameters such as FormData. For example, you can create a Server Action called addComment that expects a single parameter of type FormData.
Update Contact
The Update Contact functionality is a breeze with Next.js Server Actions. To update an existing contact, you'll need to pass the contact as an optional prop to the form component.
In the ContactForm component, you'll add the updateContact Server Action, which takes the formData as the input argument and extracts the data from the form fields.
To update the contact, you'll use Prisma Client's update API by passing the contact's ID in the where clause and the form data in the data object.
The revalidatePath method from the next/cache module is used to revalidate the current contact path, making the UI update instantly.
The button title is dynamically generated based on whether it's an add or update operation, and the action attribute of the form element is conditionally calling the addContact or updateContact Server Action.
In the updateContact Server Action, you'll create a new contact object with the specified name, phone number, and city, and then use the Prisma Client's update API to update the existing contact in the database.
Creating Server Actions
Creating Server Actions is a breeze with Next.js. You can create them in two places: a separate file, like actions.js, or within a client component.
Server Actions can be defined in a separate file with the use server directive at the top. This allows you to create multiple reusable Server Actions within a single file.
To define a Server Action in a separate file, add the use server directive at the top of the file. This marks all exports of that file as server actions.
You can also place the use server directive at the top of an async function to mark it as a server action. This is a convention provided by Next.js.
To create a Server Action, you'll need to create a separate file, like actions.ts, and add the Server Action function to it. Let's take the example of deleting a contact from the database. The deleteContactById function takes two parameters: the unique identifier of the contact to be deleted and a flag indicating whether the deletion request originates from the homepage or the view page.
Here's a breakdown of the parameters:
- Id: The unique identifier of the contact to be deleted.
- inViewRoute: A flag indicating whether the deletion request originates from the homepage or the view page.
Once you've created the Server Action, you can invoke it from a client component, like the DeleteButton component.
Best Practices and Considerations
Decoupling Server Actions is crucial for maintainable code. This means writing Server Actions in a separate file, but only if you plan to reuse the function.
Separation of concerns is key to keeping the code easier to understand, maintain, reuse, and test. This is a lesson learned from experience and the book "Clean Code".
Don't disregard the client side when working with Server Components. It's easy to forget or sacrifice user experience by moving validations to the server.
Caching results of Server Actions can improve performance by avoiding unnecessary data fetching. This is especially useful for data that doesn't frequently change.
Here are some best practices to keep in mind:
- Decouple Server Actions to keep code maintainable.
- Don't disregard the client side for a better user experience.
- Cache Server Action results to improve performance.
- Use Server Actions to handle errors gracefully.
- Protect Server Actions from unauthorized access.
Protecting Server Actions is essential for security. This means securing them just like API endpoints, with proper authentication and authorization.
Frequently Asked Questions
What is the difference between RSC and server actions?
RSCs (Rich Server Components) are a server-side framework, while Server Actions are functions that run securely on the server, triggered by client-side interactions. Think of RSCs as the foundation, and Server Actions as the executable code that brings your app to life.
Sources
- https://www.codemancers.com/blog/2024-02-08-server-actions/
- https://blog.greenroots.info/understanding-nextjs-server-actions-with-examples
- https://auth0.com/blog/using-nextjs-server-actions-to-call-external-apis/
- https://blog.openreplay.com/server-actions-in-nextjs/
- https://codeparrot.ai/blogs/nextjs-server-actions-why-and-how
Featured Images: pexels.com