DEV Community

Cover image for Implementing Type-Safe Next.js Server Actions with Zsa: A Comprehensive Guide
Vishal Yadav
Vishal Yadav

Posted on

Implementing Type-Safe Next.js Server Actions with Zsa: A Comprehensive Guide

In the realm of web development, ensuring type safety and validation is crucial for building robust and reliable applications. Next.js, a popular React framework, offers powerful server-side capabilities, but achieving end-to-end type safety can be challenging. Enter the Zsa package, a powerful tool that combines Zod and server actions to ensure type-safe Next.js server actions. In this blog, we'll explore how to leverage the Zsa package to implement type-safe server actions in your Next.js applications.

What is the Zsa Package?

The Zsa package is a library that integrates Zod, a TypeScript-first schema declaration and validation library, with server actions in Next.js. This combination provides a clean and efficient approach to type safety and input validation, enhancing both development efficiency and user experience.

Key Features of Zsa:

  • Type Safety: Ensures that all data passed to server actions is type-checked and validated.
  • Input Validation: Utilizes Zod to define and enforce input schemas.
  • Efficient Server Actions: Simplifies the creation and execution of server actions in Next.js.

Getting Started with Zsa

Let's dive into the implementation of type-safe server actions using the Zsa package.

1. Setting Up Your Project

First, ensure you have a Next.js project set up. If not, you can create one using the following command:

npx create-next-app@latest my-next-app
cd my-next-app
Enter fullscreen mode Exit fullscreen mode

Next, install the necessary dependencies:

npm install zsa zod react-hook-form
Enter fullscreen mode Exit fullscreen mode

2. Defining Input Schemas with Zod

Zod allows you to define input schemas that ensure your data is validated before reaching your server actions. Here's an example of how to define an input schema:

import { z } from 'zod';

const createCollectionSchema = z.object({
  name: z.string().min(1, "Name is required"),
  description: z.string().optional(),
});
Enter fullscreen mode Exit fullscreen mode

3. Creating Server Actions with Zsa

Using Zsa, you can create server actions that are both type-safe and validated. Here's how to implement a server action for creating a collection:

import { createServerAction } from 'zsa';
import { createCollectionSchema } from './schemas';

const createCollection = createServerAction(createCollectionSchema, async (input, context) => {
  // Your server logic here
  const { name, description } = input;
  // Assume we have a function to save the collection to the database
  await saveCollectionToDatabase(name, description, context.user.id);
  return { success: true };
});

export default createCollection;
Enter fullscreen mode Exit fullscreen mode

4. Utilizing Server Actions in Client Components

You can use server actions in your React components by leveraging React Hook Form for input validation and handling:

import React from 'react';
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import createCollection, { createCollectionSchema } from '../serverActions/createCollection';

const CreateCollectionForm = () => {
  const { register, handleSubmit, formState: { errors } } = useForm({
    resolver: zodResolver(createCollectionSchema),
  });

  const onSubmit = async (data) => {
    const result = await createCollection(data);
    if (result.success) {
      alert('Collection created successfully!');
    } else {
      alert('Error creating collection');
    }
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <div>
        <label>Name</label>
        <input {...register('name')} />
        {errors.name && <p>{errors.name.message}</p>}
      </div>
      <div>
        <label>Description</label>
        <input {...register('description')} />
      </div>
      <button type="submit">Create Collection</button>
    </form>
  );
};

export default CreateCollectionForm;
Enter fullscreen mode Exit fullscreen mode

5. Enhancing Development Efficiency with Zsa Hooks

The Zsa package provides hooks like useServerAction to simplify the execution of server actions and handling outcomes. This enhances both development efficiency and user experience:

import { useServerAction } from 'zsa';
import createCollection from '../serverActions/createCollection';

const CreateCollectionForm = () => {
  const { execute, result, error } = useServerAction(createCollection);

  const onSubmit = async (data) => {
    await execute(data);
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      {/* Form fields */}
      {result && <p>Collection created successfully!</p>}
      {error && <p>Error creating collection: {error.message}</p>}
    </form>
  );
};
Enter fullscreen mode Exit fullscreen mode

6. Centralizing Validations and User Authentication

A clean code structure often requires centralizing validations and ensuring user authentication. The Zsa package helps streamline these processes:

import { createServerAction, createProcedure } from 'zsa';
import { authenticatedProcedure } from './procedures';
import { createCollectionSchema } from './schemas';

const createCollection = createProcedure(authenticatedProcedure, createServerAction(createCollectionSchema, async (input, context) => {
  const { name, description } = input;
  await saveCollectionToDatabase(name, description, context.user.id);
  return { success: true };
}));

export default createCollection;
Enter fullscreen mode Exit fullscreen mode

Conclusion: Explore the Zsa Package

The Zsa package provides a robust solution for implementing type-safe Next.js server actions, combining the power of Zod for input validation with efficient server action handling. By leveraging these tools, you can enhance your development workflow, improve code maintainability, and ensure a seamless user experience.

Whether you're building a simple form or a complex application, the Zsa package offers features like server-side rendering, static site generation, and integration with React Query, making it a valuable ally in your web development toolkit. Explore the Zsa package and unlock the potential of type-safe Next.js server actions today!

Top comments (2)

Collapse
 
tangbaotrann profile image
baotrann

Cleanest with server action in Next.js. Great!

Collapse
 
thiagodebastos profile image
Thiago de Bastos • Edited

Great article, thank you!

For your information, the useServerAction hook has been moved to the zsa-react package: zsa.vercel.app/docs/use-server-action