Customizing form validation in React using Zod resolver for optional fields

I am currently working on creating a form using React-hook-form and zod resolver. My goal is to have all fields be optional, yet still required despite being marked as optional in the zod schema:

const schema = z.object({
    name: z.string().min(3).max(50).optional(),
    description: z.string().min(3).max(255).optional(),
    image: clientImageSchema.optional(),
  })
const {...} = useForm({ resolver: zodResolver(schema) }) 

Upon submitting the form with blank inputs, it is validating the fields as required. I am trying to identify where the error or mistake may lie. Can you help me troubleshoot this issue?

Answer №1

According to the information provided in the official documentation, it is necessary to create a union between your schema and z.literal("") in order to avoid triggering any errors when dealing with empty string values. Check out this example.

const optionalUrl = z.union([z.string().url().nullish(), z.literal("")]);

Answer №2

I encountered a similar issue and it seems to be related to handling empty strings. I came across a similar situation with enums, which you can read about here.

Currently, using the field with .preprocess() appears to resolve the issue. Here's an example:

const schema = z.object({
  // Pay attention, z.preprocess takes two arguments
  foo: z.preprocess(
    (foo) => {
      // this line won't work
      // return foo

      // this line will work, not sure why
      // console.log(typeof email)

      // I'm using this
      if (!foo || typeof foo !== 'string') return undefined
      return foo === '' ? undefined : foo
    },
    z
      .string()
      .email({
        message: 'Please correct your email address',
      })
      .optional(),
  ),
})

By implementing this, we create an optional field that is validated as an email field when it is not empty. There may be other solutions available, but this is what worked for me.

Answer №3

I have discovered a solution by providing the defaultValues when using the useForm function.

const defaultValues = {
  username: '',
  /** and so forth */
}

  useForm<UserCreateApiData>({
    resolver: yupResolver(schema),
    defaultValues,
  });

Answer №4

I stumbled upon this solution.

However, it doesn't clear the error message when the field is cleared after a failed submission.

It's also important to handle 'undefined' fields in the submit function to prevent including them in the fetch request.

const { handleSubmit, setValue, getValues, reset} = useForm<DataType>({
    resolver: zodResolver(DataSchema),
});

const preSubmit = () => {
    const values = getValues();
    if (values.name === "") setValue("name", undefined);
};

const submitForm = (data: DataType) => {
    console.log(data);
    reset();
};

<form onSubmit={(e) => {
    preSubmit();
    void handleSubmit(submitForm)(e);
}}>
    //...form fields
</form>

Answer №5

In order to make a field required in your useForm default value, insert an empty string even if it is marked as optional in the zod schema; otherwise, use undefined.

For example, consider an update user form where the password is marked as optional.

const form = useForm<z.infer<typeof updateUserSchema>>({
    resolver: zodResolver(updateUserSchema),
    reValidateMode : "onChange",
    defaultValues: {
        username: Data.User?.username ?? "", 
        email: Data.User?.email ?? "",
        password: undefined
    },
});

I opted for undefined instead of an empty string " " because it becomes required upon submission. Perhaps this is the behavior you desire? Simply use an empty string in the default value to enforce its requirement, even if it's technically optional.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Properties for a standard React component

Currently, I am developing a form component in react with typescript that requires a 'fieldStructures' and an 'onSubmit' prop. type FieldStructure { type: 'text'; name: string; label?: string; helpText?: string ...

Retrieve the Document ID from Firebase

I'm currently exploring the functionality of Firebase and enhancing my workflow with "react-firebase-hooks". Is there a way for me to retrieve both the doc id and doc data simultaneously and pass them as props? Currently, I am only able to access the ...

Exploring the Worldwide Influence of TypeScript, React, and Material-UI

I am currently following an official tutorial on creating a global theme for my app. In my root component, I am setting up the global theme like this: const themeInstance = { backgroundColor: 'cadetblue' } render ( <ThemeProvider theme ...

Guide to creating a production build for electron with react js and next framework

Currently, I am working with electron using react js and next. I am struggling to figure out how to create its production build. Can someone provide me with assistance along with a detailed step-by-step guide? app node_modules pages routes static packa ...

Custom React hook that returns an array of custom components

Do you think this approach using custom hooks is efficient? I'm providing an array as input and then iterating through it to decide which components should be shown. import React from "react"; import { Image, Paragraph, Header } from " ...

How to extract the complete URL from the API endpoint in nextjs

I'm curious if there is a way to fetch the complete URL of the current request within the API route (pages/api/myapi). The only response I have found that comes close to what I need is the req.headers.referer, but I am uncertain if this value will alw ...

Experimenting with PIXI.js and Jest within a React Single Page Application

I am currently working on a react application that utilizes PIXI.js and @inlet/react-pixi for animations. During testing with Jest, I encountered the following errors: Error: Uncaught [TypeError: Cannot read properties of null (reading 'stage' ...

Ways to access a DOM element in Next.js when the class name is dynamically generated

I am currently developing a Next.js app (version 12.1.0) and facing an issue in my Nav component. I am attempting to select a DOM element using const nav = document.querySelector('.nav'); However, this is triggering an error message: TypeError: ...

Troubleshooting the Speed Problem Between NextJs and GTM

After successfully integrating GTM into my NextJs project, I noticed a significant drop in my lighthouse performance score. Previously, I was scoring 96 but now I am only at 38. Is there a more efficient way to integrate GTM without negatively impacting th ...

Angular: Issue encountered when accessing nested properties within an interface due to reading properties of undefined

Encountering difficulties with utilizing nested property interface. //Food Interface (food.interface.ts)// export interface Food { name: string; quantity?: string; description?: string; nutrients?: { calories?: number; protein?: number; carbs?: ...

Storing TypeScript functions as object properties within Angular 6

I am working on creating a simplified abstraction using Google charts. I have implemented a chartservice that will act as the abstraction layer, providing options and data-source while handling the rest (data retrieved from a REST API). Below is the exist ...

Enhancing Typescript Arrow Function Parameters using Decorators

Can decorators be used on parameters within an arrow function at this time? For instance: const func: Function = (@Decorator param: any) => { ... } or class SomeClass { public classProp: Function = (@Decorator param: any) => { ... } } Neither W ...

Having trouble aligning image and expanding video to fit the screen in a NextJS application

I need help with: centering the image above the waitlist sign up scaling the background video in a relative way to fill the screen regardless of browser size This is the relevant part of index.js: import Head from 'next/head' import Image from ...

Ways to incorporate JavaScript code within Reactjs

I am currently working with Reactjs and using Nextjs. I am facing a challenge regarding integrating "index.html" with "index.js". At the bottom of "index.html", there is some JavaScript code that I need to transfer to another file. Can you advise me on w ...

Struggling to understand how to define and utilize Static variables in TypeScript? If you're finding that they are consistently coming up

export class myClass implements OnInit { counter = 0; static counter: any; onListItemClick(PackDef: PackDefinition): void { this.itemClicked.emit(PackDef); this.counter++; console.log(this.counter); } } and.. import { myClass } from '. ...

Should the index.js file in Next.js serve as the homepage or solely as the initial starting point?

Should I integrate my homepage directly into the index.js file, or create a separate "home-page.js" file in the pages directory? Is index.js just for initializing the application, or can it serve as a standalone page? Alternatively, should I have index.j ...

Encountering a hydration error with the useResponsive hook in Nextjs Material UI

I am facing an issue with a useResponsive hook that relies on useMediaQuery from the Material-UI library. While using Next.js with app router, the initial value of the hook returns false and then transitions to true, causing a hydration mismatch. How can I ...

Bringing in TypeScript definitions for gridster

After starting a new ionic project, I decided to include the gridster.js library by running npm install gridster and npm install @types/jquery.gridster in the root directory of my project. However, when trying to import the installed definitions, I encount ...

In the Sandbox, element.firstChild functions properly, but it does not work in the IDE

Encountered an issue that has me puzzled. To give you some context, I attempted to create a native draggable slider using React and positioned it in the center of the screen, specifically within my Codesandbox file. The code snippet I utilized is as follow ...

When a button is clicked in (Angular), it will trigger the highlighting of another button as a result of a value being modified in an array. Want to know the

Currently in the process of developing a website with Angular, I've encountered an unusual bug. The issue arises when using an *ngFor div to generate twelve buttons. <div *ngFor = "let color of colors; let i = index" style = "display ...