Server Actions in Next.js
What do Server Actions do:
- Execute asynchronous functions on the server, resulting in fewer network calls and more efficient data transfer.
- Handle tasks like data fetching, form submissions, or user data updates.
- Return data to the client, which updates the UI accordingly.
Traditional Data Fetching vs. Server Actions
Traditional Data Fetching
Previously, Next.js relied on various methods for fetching data, including:
- getStaticProps: This function runs on the server at build time to fetch data and pre-render the page. Ideal for static content that doesn't change frequently.
- getServerSideProps: This function runs on the server on every request, allowing for dynamic data fetching and personalization. Suitable for content that needs to be up-to-date for each user.
- useSWR: This is a client-side library that fetches data and manages its caching. Useful for fetching data on-demand and updating the UI reactively.
While these methods offer flexibility, they can lead to complex code and potential performance issues, especially with frequent data updates and more round-trip network requests.
Server Actions
Next.js 13 introduced server actions, a new approach that simplifies data fetching and improves application logic.
- Server Actions are functions defined with the `use server` directive.
- They can be triggered from client-side components using the `use` hook.
- Server actions run on the server, allowing access to server-side resources and functionalities.
- The return value of a server action is sent back to the client and can be used to update the UI without the need for additional network/data requests.
Server actions offer several benefits:
- Simpler code: Logic is centralized in server actions, improving code readability and maintainability.
- Improved performance: Data fetching is optimized by offloading tasks to the server.
- Enhanced security: Sensitive data processing happens on the server, reducing client-side vulnerabilities.
As you can see, the server action approach is more concise and separates data fetching logic from the component.
Server actions represent a significant step forward in Next.js data fetching. They offer a simpler, more performant, and secure way to manage data in your applications.
Example of Invoking Server Actions From <form> Elements:
Examples of Invoking Server Actions Outside of <form> Elements:
Explanation: Clicking the button triggers the handleClick
function, which sends a POST request to the /api/submit-feedback
server action. This action likely handles feedback submission and performs server-side operations. The response can be used to update the UI or handle errors.
Explanation: The useEffect
hook triggers the fetchData
function once, fetching data from the /api/fetch-data
server action. This action retrieves data, which is then used to update the component's state or render directly in the UI.
- The
sendFeedback
function uses axios to send a POST request to a feedback API (replace with your actual API endpoint). - It marks itself as a server action with
useServer
. - The ContactPage component takes user feedback in a textarea and calls
sendFeedback
on form submission. - The response from the API is handled and displayed as a message after processing.
- We define two Server Actions:
saveDraft
andsubmitPost
. saveDraft
takes the content from the request body and saves it as a draft in your database.submitPost
does the same but saves the content as a final version.
- We use
useState
to manage the content in a text area. - We use
useServerAction
to hook up to the Server Actions. handleDraftSave
is called on text area blur and triggers thesaveDraft
action with the current content.handleSubmit
is called on form submit and triggers thesubmitPost
action.- The response from the Server Actions is used to update the UI (e.g., show success message, redirect to post page).
Optimistic UI with useOptimistic and Server Actions
**What is useOptimistic?**
The useOptimistic
hook in React allows you to update the UI immediately based on the expected outcome of an asynchronous operation, even before the operation completes. This creates a more responsive and engaging user experience.
Using useOptimistic with Server Actions
This function takes the initial state and returns the updated state based on the expected outcome of the server action.
This destructures the hook to access the optimistic state, updater function, and other properties.
Use OptimisticState
in your component's render function to display the updated UI.
- Success:** Update the actual state to match the optimistic state.
- Failure:** Revert the UI to its original state using `OptimisticUpdater` with the initial value.
Server Actions vs. Server Components: Understanding the Differences
While both server actions and server components interact with your server logic, they serve distinct purposes and offer different functionalities.
Server Actions: Focused on Functionality
- **Function-based:** These are essentially asynchronous functions executed on the server.
- **Dedicated Tasks:** They handle specific tasks like data fetching, form validations, or user data updates.
- **Data Exchange:** They return data to the client, which then updates the UI.
- **Trigger Anywhere:** They can be triggered from various parts of your application, including forms, event handlers, and even other server components.
- **No Direct Rendering:** They don't directly render HTML content.
- **Examples:** Validating form submissions on the server, sending email notifications, or handling API calls.
Server Components: Rendering Server-Side UI
- **Component-Based:** These are React components rendered on the server side.
- **Reusable UI Elements:** They provide reusable UI elements that improve initial load performance and SEO.
- **HTML Rendering:** They directly render HTML content that is sent to the client.
- **Data Fetching:** They can fetch data from external sources or server-side APIs within the component itself.
- **Client Hydration:** After the initial server-side rendering, the component hydrates on the client, enabling interactive behavior.
- **Examples:** Rendering a product listing page with server-side data, building a dynamic component based on user data, or creating SEO-friendly content.
Key Differences:
Feature | Server Actions | Server Components |
---|---|---|
Type | Function | React Component |
Purpose | Specific tasks, data handling | Reusable UI elements |
Rendering | No direct HTML rendering | Renders HTML on server |
Data communication | Returns data to client | Can fetch and use data internally |
Triggering | From various application parts | Typically from client components |
Client interaction | No direct interaction | Hydrates on client for interactivity |
Examples | Form validation, email notifications | Product listing, dynamic UI, SEO content |
Conclusion
Server Actions empower developers to build performant, dynamic, secure, and user-friendly Next.js applications with several benefits:- Improved Performance: Reduce client-side JavaScript, leading to smaller client bundles and faster initial page loads. They also enable features like optimistic updates, which can further enhance the user experience.
- Enhanced Security: Help keep sensitive data and logic on the server, away from the client-side where it could be more vulnerable to attacks. They also include built-in CSRF protection to mitigate common web security threats.
- Developer Experience: Simplify data fetching and mutations by providing dedicated functions for these tasks. This can improve code readability and maintainability.
- Additionally, Server Actions enable progressive enhancement, ensuring that applications work even without JavaScript enabled.