Close Menu
    DevStackTipsDevStackTips
    • Home
    • News & Updates
      1. Tech & Work
      2. View All

      Sunshine And March Vibes (2025 Wallpapers Edition)

      May 17, 2025

      The Case For Minimal WordPress Setups: A Contrarian View On Theme Frameworks

      May 17, 2025

      How To Fix Largest Contentful Paint Issues With Subpart Analysis

      May 17, 2025

      How To Prevent WordPress SQL Injection Attacks

      May 17, 2025

      Microsoft’s allegiance isn’t to OpenAI’s pricey models — Satya Nadella’s focus is selling any AI customers want for maximum profits

      May 17, 2025

      If you think you can do better than Xbox or PlayStation in the Console Wars, you may just want to try out this card game

      May 17, 2025

      Surviving a 10 year stint in dev hell, this retro-styled hack n’ slash has finally arrived on Xbox

      May 17, 2025

      Save $400 on the best Samsung TVs, laptops, tablets, and more when you sign up for Verizon 5G Home or Home Internet

      May 17, 2025
    • Development
      1. Algorithms & Data Structures
      2. Artificial Intelligence
      3. Back-End Development
      4. Databases
      5. Front-End Development
      6. Libraries & Frameworks
      7. Machine Learning
      8. Security
      9. Software Engineering
      10. Tools & IDEs
      11. Web Design
      12. Web Development
      13. Web Security
      14. Programming Languages
        • PHP
        • JavaScript
      Featured

      NodeSource N|Solid Runtime Release – May 2025: Performance, Stability & the Final Update for v18

      May 17, 2025
      Recent

      NodeSource N|Solid Runtime Release – May 2025: Performance, Stability & the Final Update for v18

      May 17, 2025

      Big Changes at Meteor Software: Our Next Chapter

      May 17, 2025

      Apps in Generative AI – Transforming the Digital Experience

      May 17, 2025
    • Operating Systems
      1. Windows
      2. Linux
      3. macOS
      Featured

      Microsoft’s allegiance isn’t to OpenAI’s pricey models — Satya Nadella’s focus is selling any AI customers want for maximum profits

      May 17, 2025
      Recent

      Microsoft’s allegiance isn’t to OpenAI’s pricey models — Satya Nadella’s focus is selling any AI customers want for maximum profits

      May 17, 2025

      If you think you can do better than Xbox or PlayStation in the Console Wars, you may just want to try out this card game

      May 17, 2025

      Surviving a 10 year stint in dev hell, this retro-styled hack n’ slash has finally arrived on Xbox

      May 17, 2025
    • Learning Resources
      • Books
      • Cheatsheets
      • Tutorials & Guides
    Home»Development»Next.js Form Validation Using Server Actions by Zod

    Next.js Form Validation Using Server Actions by Zod

    June 13, 2024

    Server-side validation protects against invalid and malicious data, ensuring data integrity and security. In this post, we’ll look at how to utilize Zod, a declarative JavaScript validation library, for server-side form validation in a Next.js application. We will also explore how to handle validation failures provided by the server.

    Assumptions

    This blog assumes you have Next.js set up locally. If you don’t, please follow the official setup guide on the Next.js website: Next.js Setup Guide.

    Prerequisites

    In this blog post, I am using:
    – Next.js 14.x
    – Tailwind CSS
    – TypeScript
    – Zod (an NPM package for schema declaration and validation library for TypeScript)

    Why Add Server-Side Validation?

    Assume we’ve built a form with Next.js and added client-side validation. This form shows validation when the browser’s JavaScript is enabled but not when it is disabled. Without server-side validation, the form will not initiate validation and will submit the form. To prevent users from entering invalid data, we use server-side validation.

    Here’s a screenshot showing how to disable JavaScript for a particular site in Chrome:

     

    Below is a screenshot of my codebase. Once you have set up Next.js, you only need to create a components folder and an action.ts file, which should be parallel to the components folder.

    Creating the SignUp.tsx Component

    In the components folder, create SignUp.tsx:

    “use client”;

    import { FC, useState } from “react”;
    import { useFormState } from “react-dom”;
    import { createNewUser } from “@/action”;

    interface FormErrorProps {
    errors?: string[];
    }

    const FormError: FC<FormErrorProps> = ({ errors }) => {
    if (!errors?.length) return null;
    return (
    <div className=”p-2″>
    {errors.map((err, index) => (
    <p className=”text-tiny text-red-400 list-item” key={index}>
    {err}
    </p>
    ))}
    </div>
    );
    };

    const SignUp: FC = () => {
    const [date, setDate] = useState(new Date());
    const [state, formAction] = useFormState(
    createNewUser.bind(null, { date: date?.toISOString() }),
    { success: false }
    );

    return (
    <form action={formAction} className=”flex flex-col gap-y-2″>
    <label htmlFor=”name”>SignUp</label>
    <input id=”name” name=”name” className=”border-2″ />
    <FormError errors={state?.errors?.name} />

    <input id=”email” name=”email” className=”border-2″ />
    <FormError errors={state?.errors?.email} />

    <input id=”password” name=”password” className=”border-2″ />
    <FormError errors={state?.errors?.password} />

    <button type=”submit” className=”border-2″>
    Create
    </button>
    </form>
    );
    };

    export default SignUp;

     

    Note: All form field elements can remain unchecked, and we don’t need to utilize React’s useState hook for the form state. In this component, we use the React form hook useFormState, which takes a function as its first argument. In our example, we are passing a function written in action.tsx and the state object for the form:

    const [state, formAction] = useFormState(
    createNewUser.bind(null, { date: date?.toISOString() }),
    { success: false }
    );

     

    CreateNewUser Function

    We are still missing the createNewUser function used in the form’s action attribute. We’ll create this function in the action.ts file. This is a server action.

    Server actions passed to the form action attribute receive the additional data, SignUpErrors, and FormData object of the form as the first argument, which encapsulates all the data of the form. We’ll use this object to get the value of the input fields and validate with Zod. In action.ts, I wrote the Zod schema for name, email, and password validation:

    const userSchema = z.object({
    name: z.string().trim().min(3, “Name must be at least 3 characters long!”).max(18),
    email: z.string().email(“Email is invalid”),
    password: z
    .string()
    .min(8, “Password is too short!”)
    .max(20, “Password is too long”)
    .regex(passwordValidation, {
    message: “Your password is not valid”,
    })
    .optional(),
    });

     

    Checking Form Data with safeParse()

    In action.ts, we check the form data with safeParse(). If an error occurs, return an object with {success: false, errors: result.error.flatten().fieldErrors}, or on success, return {success: true}.

    actions.ts

    “use server”;

    import { z } from “zod”;

    /* TypeScript-first schema validation with static type inference */
    const passwordValidation = new RegExp(
    /^(?=.*[a-z])(?=.*[A-Z])(?=.*d)(?=.*[@$!%*?&])[A-Za-zd@$!%*?&]{8,}$/
    );

    const userSchema = z.object({
    name: z.string().trim().min(3, “Name must be at least 3 characters long!”).max(18),
    email: z.string().email(“Email is invalid”),
    password: z
    .string()
    .min(8, “Password is too short!”)
    .max(20, “Password is too long”)
    .regex(passwordValidation, {
    message: “Your password is not valid”,
    })
    .optional(),
    });

    export interface SignUpErrors {
    errors?: {
    name?: string[];
    email?: string[];
    password?: string[];
    };
    success: boolean;
    }

    export const createNewUser = async (
    date: any,
    data: SignUpErrors,
    formData: FormData
    ): Promise<SignUpErrors> => {
    const result = userSchema.safeParse({
    name: formData.get(“name”),
    email: formData.get(“email”),
    password: formData.get(“password”),
    });
    if (result.success) {
    /* Database action like creating a user */
    return { success: true };
    }
    return { success: false, errors: result.error.flatten().fieldErrors };
    };

    Note: We are using useFormState in SignUp.tsx. It only works in a Client Component, but none of its parents are marked with “use client”, so they are Server Components by default.

    Conclusion

    In this post, we covered the concept of Server Actions, their advantages over typical API routes, and using Server Actions in Next.js apps. Server Actions improve the user experience and development process by decreasing client-side JavaScript, increasing accessibility, and enabling server-side data modifications. If you want to create modern web applications with Next.js, Server Actions are a must-have tool. Experiment with Server Actions to improve your apps. Run the next bundle analyzer on a regular basis as part of your development process to keep track of changes in bundle size and detect any regressions.

     

    Source: Read More 

    Facebook Twitter Reddit Email Copy Link
    Previous ArticleSecure Accessibility with Apex
    Next Article Generating a QR code using Node.js

    Related Posts

    Development

    February 2025 Baseline monthly digest

    May 17, 2025
    Development

    Learn A1 Level Spanish

    May 17, 2025
    Leave A Reply Cancel Reply

    Continue Reading

    Mar 28, 2025: AI updates from the past week — Gemini 2.5, OpenAI 4o image generation, new reasoning agents from Microsoft, and more

    Tech & Work

    CVE-2025-46585 – Linux Kernel Out-of-bounds Array Read/Write Vulnerability

    Common Vulnerabilities and Exposures (CVEs)

    UX Design Strategy:Tips and Best Practices

    Web Development

    SonicWall Patches 3 Flaws in SMA 100 Devices Allowing Attackers to Run Code as Root

    Development

    Highlights

    Machine Learning

    How Qualtrics built Socrates: An AI platform powered by Amazon SageMaker and Amazon Bedrock

    May 15, 2025

    This post is co-authored by Jay Kshirsagar and Ronald Quan from Qualtrics. The content and…

    Best Free and Open Source Alternatives to Microsoft Photos

    December 17, 2024

    3 Essential Design Trends, August 2024

    July 29, 2024

    Microsoft bets big on Windows 11 Store with better Win32 support, faster downloads, and more

    December 7, 2024
    © DevStackTips 2025. All rights reserved.
    • Contact
    • Privacy Policy

    Type above and press Enter to search. Press Esc to cancel.