我正在使用react Typescript构建一个带有Zod验证模式的表单.

What I am trying to achieve?个 因此,我希望根据另一个字段的值呈现条件.每个国家都有自己的电话代码和电话号码格式.每次有人 Select 电话代码时,我希望电话号码字段具有不同的验证规则.这就是我到目前为止所拥有的.这基本上是我实际项目的复制.

import { Formik, Field, Form, FormikHelpers } from 'formik'
import { toFormikValidationSchema } from 'zod-formik-adapter'
import { z } from 'zod'
import './App.css'


const FormField = z.object({
  firstName: z.string().max(6, 'Too long'),
  lastName: z.string(),
  email: z.string(),
  phoneCode: z.string(),
  phoneNumber: z.string()
})

const Register = FormField.required()
.refine((input) => {
  return input.phoneCode === '0044';
}, 'Phone code must be 0044');


Register.parse({
  firstName: 'fewfwf',
  lastName: 'Doe',
  email: 'jogn@doe.com',
  phoneCode: '0044',
  phoneNumber: '0044'
})

type Values = z.infer<typeof Register>

function App() {

  return (
    <>
      <Formik
        initialValues={{
          firstName: '',
          lastName: '',
          email: '',
          phoneCode: '',
          phoneNumber: ''
        }}
        onSubmit={(
          values: Values,
          { setSubmitting }: FormikHelpers<Values>
        ) => {
          setTimeout(() => {
            alert(JSON.stringify(values, null, 2));
            setSubmitting(false);
          }, 500);
        }}
        validationSchema={toFormikValidationSchema(FormField)}
      >
        {({ errors, touched }) => (
          <Form>
             {errors.firstName ? (<div>{errors.firstName}</div>) : null}
            <label htmlFor="firstName">First Name</label>
            <Field id="firstName" name="firstName" placeholder="John" />

            <label htmlFor="lastName">Last Name</label>
            <Field id="lastName" name="lastName" placeholder="Doe" />

            <label htmlFor="email">Email</label>
            <Field
              id="email"
              name="email"
              placeholder="john@acme.com"
              type="email"
            />

            <label htmlFor="phoneCode">PhoneCode</label>
            <Field id="phoneCode" name="phoneCode" placeholder="+44" />

            {errors.phoneNumber && touched.phoneNumber ? (<div>{errors.phoneNumber}</div>) : null}
            <label htmlFor="phoneNumber">PhoneNumber</label>
            <Field id="phoneNumber" name="phoneNumber" placeholder="789434556" />

            <button type="submit">Submit</button>
          </Form>
        )}
      </Formik>

    </>
  )
}

export default App

如您所见,我使用了.finine()并添加了一些随机条件进行测试.当我通过parse方法运行它时,它正确地验证并工作,但是,当我从前端提交表单时,它仍然执行,即使phoneCode不等于‘0044’.这是.finine方法的正常行为吗?有没有其他更实际的方法?

推荐答案

您可以修改现有代码以包括此动态验证:

创建用于动态电话号码验证的函数: 定义一个函数,该函数根据选定的电话代码返回电话号码的Zod架构.

更新Formik验证架构: 使用Formik验证方案中的动态电话号码验证功能.

更新表单组件: 使用Formik的上下文访问电话代码的当前值,并将相应的验证模式应用于电话号码字段.

import { Formik, Field, Form, FormikHelpers, useFormikContext } from 'formik';
import { toFormikValidationSchema } from 'zod-formik-adapter';
import { z } from 'zod';
import './App.css';

// Function to get dynamic phone number validation schema based on phone code
const getPhoneNumberSchema = (phoneCode: string) => {
  switch (phoneCode) {
    case '0044':
      return z.string().length(10, 'UK phone number must be 10 digits long');
    // Add cases for other phone codes with their respective validation rules
    default:
      return z.string();
  }
};

const FormField = z.object({
  firstName: z.string().max(6, 'Too long'),
  lastName: z.string(),
  email: z.string().email(),
  phoneCode: z.string(),
  phoneNumber: z.string() // Default validation, will be dynamically updated
});

type Values = z.infer<typeof FormField>;

function App() {
  return (
    <>
      <Formik
        initialValues={{
          firstName: '',
          lastName: '',
          email: '',
          phoneCode: '',
          phoneNumber: ''
        }}
        onSubmit={(values: Values, { setSubmitting }: FormikHelpers<Values>) => {
          setTimeout(() => {
            alert(JSON.stringify(values, null, 2));
            setSubmitting(false);
          }, 500);
        }}
        validationSchema={() => {
          const { values } = useFormikContext<Values>();
          return toFormikValidationSchema(FormField.extend({
            phoneNumber: getPhoneNumberSchema(values.phoneCode)
          }));
        }}
      >
        {({ errors, touched }) => (
          <Form>
            {/* ... other fields ... */}
            <Field id="phoneCode" name="phoneCode" placeholder="+44" />
            <Field id="phoneNumber" name="phoneNumber" placeholder="789434556" />
            {errors.phoneNumber && touched.phoneNumber && <div>{errors.phoneNumber}</div>}
            <button type="submit">Submit</button>
          </Form>
        )}
      </Formik>
    </>
  )
}

export default App;

根据选定的电话代码,getPhoneNumberSchema函数为电话号码字段返回不同的Zod模式. Formik validationSchema是使用当前表单值动态生成的,允许电话号码验证根据选定的电话代码进行调整. 确保在getPhoneNumberSchema函数中处理不同的电话代码及其各自的验证规则.

Typescript相关问答推荐

Angular 17 -如何在for循环内创建一些加载?

动态调用类型化函数

如何通过TypeScript中的工厂函数将区分的联合映射到具体的类型(如类)?

如何在TypeScrip中从字符串联合类型中省略%1值

使用axios在ngOnInit中初始化列表

使用2个泛型类型参数透明地处理函数中的联合类型

<;T扩展布尔值>;

Angular文件上传到Spring Boot失败,多部分边界拒绝

使用KeyOf和Never的循环引用

布局组件中的Angular 17命名路由出口

常量类型参数回退类型

在类型脚本中将泛型字符串数组转换为字符串字母并集

与toast.error一起react 中的Async TUNK错误消息

字幕子集一个元组的多个元素

三重融合视角与正交阵

接口中可选嵌套属性的类型判断

组件使用forwardRef类型脚本时传递props

元组解释

对于通过 Axios 获取的数据数组,属性map在类型never上不存在

在Nestjs中,向模块提供抽象类无法正常工作