首頁 > web前端 > js教程 > 具有 discriminatedUnion 和 React Hook Form 的動態表單

具有 discriminatedUnion 和 React Hook Form 的動態表單

Susan Sarandon
發布: 2024-12-24 03:41:14
原創
1051 人瀏覽過

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>
              )}
            </div>

            <div classname="form">
              銀行代碼標籤>
              >
              {bankTransferErrors?.bankCode?.message && (
                <span classname="錯誤訊息">
                  {bankTransferErrors.bankCode.message}
                </span>
              )}
            </div>
          </div>;
        );

      案例 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>
              )}
            </div>
          </div>
        );

      案例 PaymentMethodEnum.PAYPAL:
        const paypalErrors = getErrorsByPaymentType(錯誤, paymentType);
        返回 (
          <div classname="form">
            電子郵件標籤>
            >
            {paypalErrors?.email?.message && (
              <span classname="errormessage">{paypalErrors.email.message}</span>;
            )}
          </div>
        );

      預設:
        拋出新的錯誤(
          “詳盡的防護錯誤:收到值” 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中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板