ホームページ >ウェブフロントエンド >jsチュートリアル >DiscrixUnion と React Hook Form を使用した動的フォーム

DiscrixUnion と React Hook Form を使用した動的フォーム

Susan Sarandon
Susan Sarandonオリジナル
2024-12-24 03:41:14987ブラウズ

Dynamic forms with discriminatedUnion and React Hook Form

フォーム検証は、最新の Web アプリケーションの重要な側面です。 React Hook Form (RHF) や Zod などのライブラリを使用すると、支払い方法などの複雑な構造を含む動的フォームを効率的に検証できます。この記事では、Zod と RHF の両方を使用して、強力な DiscrixUnion を使用して動的にフォームを検証する方法について説明します。

DistributedUnion とは何ですか?

DistributedUnion は、構造が異なるものの、共通の識別フィールドを共有するオブジェクトをモデル化するために使用される高度な型指定手法です。この判別フィールドは、どのサブタイプが使用されているかを識別し、それに応じて検証または操作を実行するために使用されます。
たとえば、次の 3 種類の支払い方法を含む支払いフォームを考えてみましょう。

  1. クレジット カード (カード番号と CVV が必要です)
  2. PayPal (メールアドレスが必要です)
  3. 銀行振込 (口座番号と銀行コードが必要です)。 これらの型はそれぞれ、discricedUnion を使用してモデル化できます。 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 は type フィールドを検査します:

    • タイプが「creditCard」の場合、Zod は次に従って検証します。 最初のオブジェクトで定義された制約。
    • タイプが「paypal」の場合、リンクされているルールのみをチェックします PayPal オブジェクトに送信します。
    • タイプが「bankTransfer」の場合、次に従って検証されます。 銀行振込の基準
  2. 厳密な検証:

    • 各タイプは独立しています。ユーザーの場合 無効なタイプが指定されているか、必須フィールドが省略されています。 Zod は特定のエラーをトリガーします。
  3. React フック フォームのシンプルさ:

    • スキーマにより、RHF は検証を動的に適応させることができます type フィールドに従って、ロジックを簡素化します。 フォーム。

**

なぜここで DiscrixUnion を使用するのでしょうか?

**

  1. 責任の明確な分離
    • 各支払い方法に特有の禁止事項 互いに干渉し合い、干渉し合います。
  2. 柔軟性
    • 新しいタイプを許可します (新しい支払いなど) メソッド)を簡単に追加できます。タイプ (新しい支払い方法など)。
  3. セキュリティ
    • 無効な値が検出されることを確認します。 検証時間。

**

Reactフックフォームとの統合

**
React Hook Form を使用すると、高パフォーマンスと柔軟性を維持しながら、フォームの管理が容易になります。ここでは、Zod と RHF を統合して、distributedUnion に基づいてフォームを検証する方法を説明します。

import { useForm, SubmitHandler, FieldErrors } from 'react-hook-form';
import { zodResolver } から '@hookform/resolvers/zod';
'./payment.css' をインポートします。
輸入 {
  PaymentMethodEnum、
  PaymentMethodスキーマ、
  PaymentMethodSchemaType、
'../validators/validate-payment-schema' から;

const 支払い = () => {
  const form = useForm<PaymentMethodSchemaType>({
    リゾルバー: zodResolver(paymentMethodSchema())、
    デフォルト値: {
      タイプ: PaymentMethodEnum.CREDIT_CARD、
    }、
  });

  const {レジスタ、フォームステート、ハンドルサブミット} = フォーム;

  const {エラー} = formState;

  constpaymentType = 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(errors,paymentType);

        戻る (
          <div>
            <div className="フォーム">
              <label>口座番号</label>
              
              {bankTransferErrors?.accountNumber?.message && (
                <スパンクラス名="エラーメッセージ">
                  {bankTransferErrors.accountNumber.message}
                </span>
              )}
            </div>

            <div className="フォーム">
              <label>銀行コード</label>
              
              {bankTransferErrors?.bankCode?.message && (
                <スパンクラス名="エラーメッセージ">
                  {bankTransferErrors.bankCode.message}
                </span>
              )}
            </div>
          </div>
        );

      ケース PaymentMethodEnum.CREDIT_CARD:
        const CreditCardErrors = getErrorsByPaymentType(errors,paymentType);
        戻る (
          <div>
            <div className="フォーム">
              <label>カード番号</label>
              
              {creditCardErrors?.cardNumber && (
                <スパンクラス名="エラーメッセージ">
                  {creditCardErrors.cardNumber.message}
                </span>
              )}
            </div>

            <div className="フォーム">
              <label>CVV</label>
              
              {creditCardErrors?.cvv && (
                <スパンクラス名="エラーメッセージ">
                  {creditCardErrors.cvv.message}
                </span>
              )}
            </div>
          </div>
        );

      PaymentMethodEnum.PAYPAL の場合:
        const paypalErrors = getErrorsByPaymentType(errors,paymentType);
        戻る (
          <div className="フォーム">
            <label>メール</label>
            
            {paypalErrors?.email?.message && (
              <span className="errormessage">{paypalErrors.email.message}</span>
            )}
          </div>
        );

      デフォルト:
        新しいエラーをスロー(
          「徹底的なガード エラー: 値を受け取りました」paymentType
        );
    }
  })();

  戻る (
    <form className="form-wrapper" onSubmit={handleSubmit(onSubmit)}>
      <div className="フォーム">



<p>**</p>

<h2>
  
  
  結論
</h2>

<p>**<br>
それで皆さん。この記事がお役に立てば幸いです。 DiscrixUnion は、さまざまな方法で使用できるユーティリティ タイプです。 DiscrixUnion を使用する方法が他にもあると思われる場合は、コメントでお知らせください。この記事をお読みいただきありがとうございます。次の記事でお会いしましょう?</p>

<p>テスト アプリケーションのリンク: <br>
https://stackblitz.com/edit/vitejs-vite-ppgw9zrb?file=src/pages/payments.tsx</p>


          

            
        </paymentmethodschematype>

以上がDiscrixUnion と React Hook Form を使用した動的フォームの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。