最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

How to write validation on zod depending on react state - Stack Overflow

programmeradmin2浏览0评论

There is a state that can take the values true or false. If state is true, the field is required, otherwise it is not. How to validate depending on the condition? I found an example:

const [selectOption, setSelectOption] = useState(null);

const stepTwoForm = useForm({
  resolver: zodResolver(stepTwoSchema.refine(
    (data) => ({ ...data, select: selectOption }),
  )),
});

And then

export const stepTwoSchema = z.object({
  inputOne: z.string().optional(),
  inputTwo: z.string().optional(),
}).superRefine((data, ctx) => {
  const selectedOption = ctx.parent?.select;

  if (selectedOption === 'A' && !data.inputOne?.trim()) {
    ctx.addIssue({
      path: ['inputOne'],
      message: 'Input 1 is required when Option A is selected.',
    });
  }

  if (selectedOption === 'B' && !data.inputTwo?.trim()) {
    ctx.addIssue({
      path: ['inputTwo'],
      message: 'Input 2 is required when Option B is selected.',
    });
  }
});

But this is for the old version of zod. In the new version, ctx does not have the 'parent' property.

There is a state that can take the values true or false. If state is true, the field is required, otherwise it is not. How to validate depending on the condition? I found an example:

const [selectOption, setSelectOption] = useState(null);

const stepTwoForm = useForm({
  resolver: zodResolver(stepTwoSchema.refine(
    (data) => ({ ...data, select: selectOption }),
  )),
});

And then

export const stepTwoSchema = z.object({
  inputOne: z.string().optional(),
  inputTwo: z.string().optional(),
}).superRefine((data, ctx) => {
  const selectedOption = ctx.parent?.select;

  if (selectedOption === 'A' && !data.inputOne?.trim()) {
    ctx.addIssue({
      path: ['inputOne'],
      message: 'Input 1 is required when Option A is selected.',
    });
  }

  if (selectedOption === 'B' && !data.inputTwo?.trim()) {
    ctx.addIssue({
      path: ['inputTwo'],
      message: 'Input 2 is required when Option B is selected.',
    });
  }
});

But this is for the old version of zod. In the new version, ctx does not have the 'parent' property.

Share Improve this question edited Mar 31 at 12:38 Александр Кос asked Mar 31 at 9:32 Александр КосАлександр Кос 1321 silver badge9 bronze badges
Add a comment  | 

2 Answers 2

Reset to default 2

To validate fields conditionally in Zod, you have two main approaches:

  1. Include the condition in the form data:

    const schema = z.object({
      selectOption: z.string(), // Your condition
      inputOne: z.string().optional(),
      inputTwo: z.string().optional()
    }).superRefine((data, ctx) => {
      if (data.selectOption === "A" && !data.inputOne?.trim()) {
        ctx.addIssue({
          code: "custom",
          path: ["inputOne"],
          message: "Input 1 is required for Option A"
        });
      }
      // Similar for other conditions
    });
    
    // Usage:
    useForm({
      resolver: zodResolver(schema)
    });
    
  2. Pass the condition as a parameter:

    const createSchema = (selectOption) => 
      z.object({
        inputOne: z.string().optional(),
        inputTwo: z.string().optional()
      }).superRefine((data, ctx) => {
        if (selectOption === "A" && !data.inputOne?.trim()) {
          ctx.addIssue({/*...*/});
        }
        // Other conditions
      });
    
    // Usage:
    useForm({
      resolver: zodResolver(createSchema(currentSelection))
    });
    

    Choose based on whether the condition is part of your form state or external and handle the selectOption data, either include the condition in your form data or pass it externally.

In this scenario, I would simply move selectOption to be inside your schema. You can then access the value from data in your .refine() or .superRefine() function.

发布评论

评论列表(0)

  1. 暂无评论