Server Actions in Next.js 14: A Comprehensive Guide

Server Actions in Next.js 14: A Comprehensive Guide

Server Actions in Next.js 14 streamline server-side logic by allowing it to be executed directly within React components, reducing the need for separate API routes and simplifying data handling.

Server Actions in Next.js 14 streamline server-side logic by allowing it to be executed directly within React components, reducing the need for separate API routes and simplifying data handling.

Jul 21, 2024

Framework

Jul 21, 2024

Framework

Jul 21, 2024

Framework

Next.js 14 introduced Server Actions, a powerful feature that allows developers to handle asynchronous operations on the server. In this guide we are gonna explore Server Actions in detail so lets start with it.

Introduction to Server Actions

Server Actions in Next.js 14 are basically asynchronous functions that run on the server. They can handle data mutations, form submissions etc. They can also be used for fetching data but we next.js doesn’t recommends to use it for fetching purpose. It recommends fetching data in server components directly.
These server actions can be called from both the Server Components and Client Components.

But what are the Advantages of using Server Actions?

Security: Sensitive operations and data stay on the server.

Performance: Offloads processing to the server, reducing client workload.

Convenience: Simplifies code by keeping server logic within the Next.js framework.

Defining Server Actions

To define a Server Action, use the use server directive at the top of an asynchronous function. This directive can be placed inside a function or at the top of a module to mark all exports as Server Actions.

// app/actions.ts
'use server';

export async function createUser(formData: FormData) {
  // Process form data on the server
  const user = await db.users.create({ data: formData });
  return user;
}

In this example, createUser is a Server Action that processes form data and creates a user in the database.


Using Server Actions in Server Components

Server Components are the one that render on the server, We can call Server Actions directly within them.

import { createUser } from './actions';

export default function Page() {
  const handleSubmit = async (formData: FormData) => {
    await createUser(formData);
  };

  return (
    <form action={handleSubmit}>
      <input type="text" name="username" required />
      <button type="submit">Create User</button>
    </form>
  );
}


In this example, the form submission is handled by the createUser Server Action, which processes the data on the server.

Using Server Actions in Client Components

Client Components are the components which are rendered on the client. We can only import actions marked with the module-level use server directive. This allows us to call Server Actions from Client Components securely.

// app/actions.ts
'use server';

export async function createUser(formData: FormData) {
  const user = await db.users.create({ data: formData });
  return user;
}


// app/client-component.tsx
'use client';
import { createUser } from './actions';

export default function ClientComponent() {
  const handleSubmit = async (event) => {
    event.preventDefault();
    const formData = new FormData(event.target);
    await createUser(formData);
  };

  return (
    <form onSubmit={handleSubmit}>
      <input type="text" name="username" required />
      <button type="submit">Create User</button>
    </form>
  );
}


Here, createUser is a Server Action called from a Client Component, handling form submission and data processing on the server.

Server Actions will be called even if the javascript isn’t loaded or it is disabled. They can be called not just in Form but can be invoked from event handlers, useEffect hooks or any other 3rd -party library making them quite flexible and easy to use.

Advanced Usage of Server Actions

Server Actions can be utilized in various advanced scenarios, including handling optimistic updates, error handling, and revalidation.

Optimistic Updates

Optimistic updates allow the UI to update immediately while the Server Action is still processing. This will enhance the user experience by providing instant feedback.

// app/page.tsx
'use client';
import { useOptimistic } from 'react';
import { createUser } from './actions';

export default function Page() {
  const [optimisticUser, setOptimisticUser] = useOptimistic(null, (state, user) => user);

  const handleSubmit = async (event) => {
    event.preventDefault();
    const formData = new FormData(event.target);
    const newUser = { username: formData.get('username') };
    setOptimisticUser(newUser);
    await createUser(formData);
  };

  return (
    <div>
      <form onSubmit={handleSubmit}>
        <input type="text" name="username" required />
        <button type="submit">Create User</button>
      </form>
      {optimisticUser && <p>Creating user: {optimisticUser.username}</p>}
    </div>
  );
}


Error Handling

Proper error handling ensures that your application can gracefully handle failures in Server Actions.

// app/actions.ts
'use server';

export async function createUser(formData: FormData) {
  try {
    const user = await db.users.create({ data: formData });
    return user;
  } catch (error) {
    throw new Error('Failed to create user');
  }
}

Revalidating Data

Revalidation method is crucial for ensuring that the cached data remains fresh. Next.js provides two primary methods for revalidating data: revalidating by tag and revalidating by path.

Revalidating by Tag

Tags can be used to group related cache entries, which can then be invalidated together and can be fetched again.

Revalidating by Tag

// app/actions.ts
'use server';
import { revalidateTag } from 'next/cache';

export async function createUser(formData: FormData) {
  const user = await db.users.create({ data: formData });
  revalidateTag('users');
  return user;
}

Calling Revalidate Tag in a Client Component

// app/client-component.tsx
'use client';
import { createUser } from './actions';

export default function ClientComponent() {
  const handleSubmit = async (event) => {
    event.preventDefault();
    const formData = new FormData(event.target);
    await createUser(formData);
  };

  return (
    <form onSubmit={handleSubmit}>
      <input type="text" name="username" required />
      <button type="submit">Create User</button>
    </form>
  );
}

Revalidating by Path

Paths can be revalidated to ensure specific routes are updated with fresh data.

Revalidating by Path

// app/actions.ts
'use server';
import { revalidatePath } from 'next/cache';

export async function createUser(formData: FormData) {
  const user = await db.users.create({ data: formData });
  revalidatePath('/users');
  return user;
}

Calling Revalidate Path in a Client Component

// app/client-component.tsx
'use client';
import { createUser } from './actions';

export default function ClientComponent() {
  const handleSubmit = async (event) => {
    event.preventDefault();
    const formData = new FormData(event.target);
    await createUser(formData);
  };

  return (
    <form onSubmit={handleSubmit}>
      <input type="text" name="username" required />
      <button type="submit">Create User</button>
    </form>
  );
}

Understanding Revalidation with a Diagram

Here’s a diagram to help us visualize how revalidation works in Next.js 14:


In this diagram:

  • The Client Component submits a form, triggering the createUser Server Action.

  • The Server Action processes the data and updates the database.

  • The Server Action then revalidates the tag ‘users’ and the path ‘/users’ to ensure that any cached data related to users is refreshed.


Conclusion

Server Actions in Next.js 14 offer a powerful and flexible way to handle server-side logic, making it easier to build secure, performant, and maintainable applications.We have covered the basics and advanced usage of Server Actions, but the best way to master them is through practice and experimentation so try it yourself.Happy Coding 👨‍💻!!



Discover More Insights

Continue learning with our selection of related topics. From AI to web development, find more articles that spark your curiosity.

DevOps and Infrastructure

Dec 27, 2024

The Power of Serverless Computing

Serverless computing eliminates the need to manage infrastructure by dynamically allocating resources, enabling developers to focus on building applications. It offers scalability, cost-efficiency, and faster time-to-market.

Understanding OAuth: Simplifying Secure Authorization
Understanding OAuth: Simplifying Secure Authorization
Understanding OAuth: Simplifying Secure Authorization
Understanding OAuth: Simplifying Secure Authorization

Authentication and Authorization

Dec 11, 2024

Understanding OAuth: Simplifying Secure Authorization

OAuth (Open Authorization) is a protocol that allows secure, third-party access to user data without sharing login credentials. It uses access tokens to grant limited, time-bound permissions to applications.

Web Development

Nov 25, 2024

Clean Code Practices for Frontend Development

This blog explores essential clean code practices for frontend development, focusing on readability, maintainability, and performance. Learn how to write efficient, scalable code for modern web applications

Cloud Computing

Oct 28, 2024

Multitenant Architecture for SaaS Applications: A Comprehensive Guide

Multitenant architecture in SaaS enables multiple users to share one application instance, with isolated data, offering scalability and reduced infrastructure costs.

API

Oct 16, 2024

GraphQL: The API Revolution You Didn’t Know You Need

GraphQL is a flexible API query language that optimizes data retrieval by allowing clients to request exactly what they need in a single request.

CSR vs. SSR vs. SSG: Choosing the Right Rendering Strategy for Your Website
CSR vs. SSR vs. SSG: Choosing the Right Rendering Strategy for Your Website
CSR vs. SSR vs. SSG: Choosing the Right Rendering Strategy for Your Website
CSR vs. SSR vs. SSG: Choosing the Right Rendering Strategy for Your Website

Technology

Sep 27, 2024

CSR vs. SSR vs. SSG: Choosing the Right Rendering Strategy for Your Website

CSR builds pages in the browser for fast interactions but slower initial loads. SSR renders HTML on the server for better SEO and quicker first loads, but increases server load. SSG pre-renders pages for fast loading and great SEO but is less dynamic for updates.

ChatGPT Opean AI O1
ChatGPT Opean AI O1
ChatGPT Opean AI O1
ChatGPT Opean AI O1

Technology & AI

Sep 18, 2024

Introducing OpenAI O1: A New Era in AI Reasoning

OpenAI O1 is a revolutionary AI model series that enhances reasoning and problem-solving capabilities. This innovation transforms complex task management across various fields, including science and coding.

Tech & Trends

Sep 12, 2024

The Impact of UI/UX Design on Mobile App Retention Rates | TechTose

Mobile app success depends on user retention, not just downloads. At TechTose, we highlight how smart UI/UX design boosts engagement and retention.

Want to work together?

We love working with everyone, from start-ups and challenger brands to global leaders. Give us a buzz and start the conversation.   

Want to work together?

We love working with everyone, from start-ups and challenger brands to global leaders. Give us a buzz and start the conversation.   

Want to work together?

We love working with everyone, from start-ups and challenger brands to global leaders. Give us a buzz and start the conversation.