首页 > web前端 > js教程 > 具有 discriminatedUnion 和 React Hook Form 的动态表单

具有 discriminatedUnion 和 React Hook Form 的动态表单

Susan Sarandon
发布: 2024-12-24 03:41:14
原创
990 人浏览过

Dynamic forms with discriminatedUnion and React Hook Form

表单验证是现代 Web 应用程序的一个重要方面。借助 React Hook Form (RHF) 和 Zod 等库,您可以有效地验证动态表单,包括具有复杂结构(例如支付方式)的表单。本文介绍了如何使用 Zod 和 RHF 来使用强大的 discriminatedUnion 动态验证表单。

什么是受歧视联盟?

discriminatedUnion 是一种高级类型技术,用于对具有不同结构但共享公共判别字段的对象进行建模。该判别字段用于识别正在使用哪种子类型并相应地执行验证或操作。
例如,考虑一个可能包含三种付款方式的付款表单:

  1. 信用卡(需要卡号和CVV)
  2. PayPal(需要电子邮件地址)
  3. 银行转账(需要账号和银行代码)。 这些类型中的每一种都可以使用 discriminatedUnion 进行建模 使用 Zod 进行数据建模的示例
import * as zod from "zod"

const IsNotEmptyString = (message: string) => zod.string({message}).min(1, {message})


export enum PaymentMethodEnum {
   CREDIT_CARD ="creditCard", 
   PAYPAL = "paypal", 
   BANKTRANSFER ="bankTransfer"
}

  const creditCardSchema = zod.object({
   type: zod.literal(PaymentMethodEnum.CREDIT_CARD),
   cardNumber: zod.string().regex(/^\d{16}$/, "The card number must contain 16 digits"),
   cvv: zod.string().regex(/^\d{3}$/, "The Card Validation Code must contain 3 digits"),
 })

 const paypalSchema =  zod.object({
   type: zod.literal(PaymentMethodEnum.PAYPAL),
   email: zod.string().email("PayPal email is invalid"),
 })

 const bankTransferSchema =  zod.object({
   type: zod.literal(PaymentMethodEnum.BANKTRANSFER),
   accountNumber: IsNotEmptyString("The account number must contain at least 10 characters"),
   bankCode: IsNotEmptyString("The bank code must contain at least 4 characters")
 })

export const paymentMethodSchema =  () => zod.discriminatedUnion("type",[
   creditCardSchema, paypalSchema,bankTransferSchema
]); 

export type PaymentMethodSchemaType = zod.infer < ReturnType <typeof paymentMethodSchema>>

登录后复制

**

验证如何进行?

**

  1. discriminatedUnion 检查类型字段:

    • 如果类型是‘creditCard’,Zod 根据 第一个对象中定义的约束。
    • 如果类型为“paypal”,则仅检查链接的规则 到 PayPal 对象。
    • 如果类型是“bankTransfer”,则根据 银行转账标准。
  2. 严格验证:

    • 每种类型都是独立的。如果一个用户 提供无效类型或省略必填字段, Zod 触发特定错误。
  3. React Hook 表单的简单性:

    • 该模式允许 RHF 动态调整验证 根据type字段,简化其中的逻辑 表格。

**

为什么在这里使用 discriminatedUnion ?

**

  1. 明确的职责分离
    • 每种付款方式都有特定的规则,不得 互相干扰互相干扰。
  2. 灵活性
    • 允许新类型(例如新的付款 方法)可以轻松添加。类型(例如,新的付款方式)。
  3. 安全
    • 确保在以下位置检测到任何无效值 验证时间。

**

与 React Hook 表单集成

**
React Hook Form 可以轻松管理表单,同时保持高性能和灵活性。下面介绍如何集成 Zod 和 RHF 来验证基于 discriminatedUnion 的表单。

从 'react-hook-form' 导入 { useForm, SubmitHandler, FieldErrors };
从 '@hookform/resolvers/zod' 导入 { zodResolver };
导入'./ payment.css';
进口 {
  付款方式枚举,
  付款方式架构,
  PaymentMethodSchemaType,
来自 '../validators/validate- payment-schema';

常量支付 = () => {
  const form = useForm<paymentmethodschematype>({
    解析器:zodResolver( paymentMethodSchema() ),
    默认值:{
      类型:PaymentMethodEnum.CREDIT_CARD,
    },
  });

  const { 注册,formState,handleSubmit } = 表单;

  const { 错误 } = formState;

  const paymentType = form.watch().type;

  const handleChangePaymentType = (类型: PaymentMethodEnum) => {
    form.setValue('类型', 类型);
  };

  const handleResetForm = () =>; {
    form.reset(GetErrorState( paymentType) );
  };

  const onSubmit: SubmitHandler<paymentmethodschematype>; =(数据)=> {
    console.log('数据', 数据);
  };

  const PaymentTypeFormNode: React.ReactNode = (() => {
    开关(付款类型){
      案例 PaymentMethodEnum.BANKTRANSFER:
        const BankTransferErrors = getErrorsByPaymentType(错误, paymentType);

        返回 (
          <div>
            <div className="form">
              帐号标签>
              >
              {bankTransferErrors?.accountNumber?.message && (
                <span classname="错误消息">
                  {bankTransferErrors.accountNumber.message}
                </span>
              )}
            </span>
</div>

            <div className="form">
              银行代码标签>
              >
              {bankTransferErrors?.bankCode?.message && (
                <span className="错误消息">
                  {bankTransferErrors.bankCode.message}
                </span>
              )}
            
          ;
        );

      案例 PaymentMethodEnum.CREDIT_CARD:
        const CreditCardErrors = getErrorsByPaymentType(错误, paymentType);
        返回 (
          <div>
            <div className="form">
              卡号标签>
              >
              {creditCardErrors?.cardNumber && (
                <span className="错误消息">
                  {creditCardErrors.cardNumber.message}
                </span>
              )}
            </div>

            <div className="form">
              CVV标签>
              >
              {creditCardErrors?.cvv && (
                <span className="错误消息">
                  {creditCardErrors.cvv.message}
                </span>
              )}
            
          
        );

      案例 PaymentMethodEnum.PAYPAL:
        const paypalErrors = getErrorsByPaymentType(错误, paymentType);
        返回 (
          <div className="form">
            电子邮件标签>
            >
            {paypalErrors?.email?.message && (
              <span classname="errormessage">{paypalErrors.email.message}</span>;
            )}
          
        );

      默认:
        抛出新的错误(
          “详尽的防护错误:收到值” paymentType
        );
    }
  })();

  返回 (
    <form classname="form-wrapper" onsubmit="{handleSubmit(onSubmit)}">;
      <div classname="form">



<p>**</p>

<h2>
  
  
  结论
</h2>

<p>**<br>
就是这样,伙计们。我希望这篇文章对您有所帮助。 discriminatedUnion 是一种实用程序类型,可以通过多种方式使用。如果您认为还有更多使用 discriminatedUnion 的方法,请在评论中告诉我。感谢您阅读本文。我们下一篇文章见?.</p>

<p>测试申请链接:<br>
https://stackblitz.com/edit/vitejs-vite-ppgw9zrb?file=src/pages/ payments.tsx</p>


          </div>

            
        </form></paymentmethodschematype></paymentmethodschematype>
登录后复制

以上是具有 discriminatedUnion 和 React Hook Form 的动态表单的详细内容。更多信息请关注PHP中文网其他相关文章!

来源:dev.to
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
作者最新文章
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板