Rumah > hujung hadapan web > tutorial js > Borang dinamik dengan discriminatedUnion dan React Hook Form

Borang dinamik dengan discriminatedUnion dan React Hook Form

Susan Sarandon
Lepaskan: 2024-12-24 03:41:14
asal
988 orang telah melayarinya

Dynamic forms with discriminatedUnion and React Hook Form

Pengesahan borang ialah aspek penting dalam aplikasi web moden. Dengan perpustakaan seperti React Hook Form (RHF) dan Zod, anda boleh mengesahkan borang dinamik dengan cekap, termasuk yang mempunyai struktur kompleks seperti kaedah pembayaran. Artikel ini menerangkan cara menggunakan kedua-dua Zod dan RHF untuk mengesahkan borang secara dinamik menggunakan discriminatedUnion yang berkuasa.

Apakah itu Kesatuan diskriminasi?

DiscriminatedUnion ialah teknik menaip lanjutan yang digunakan untuk memodelkan objek dengan struktur berbeza tetapi berkongsi medan diskriminasi yang sama. Medan diskriminasi ini digunakan untuk mengenal pasti subjenis yang sedang digunakan dan untuk melaksanakan pengesahan atau manipulasi sewajarnya.
Sebagai contoh, pertimbangkan borang pembayaran yang mungkin mengandungi tiga jenis kaedah pembayaran:

  1. Kad kredit (memerlukan nombor kad dan CVV)
  2. PayPal (memerlukan alamat e-mel)
  3. Pemindahan bank (memerlukan nombor akaun dan kod bank). Setiap jenis ini boleh dimodelkan menggunakan discriminatedUnion Contoh Pemodelan Data dengan 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>>

Salin selepas log masuk

**

Bagaimanakah pengesahan berfungsi?

**

  1. discriminatedUnion memeriksa medan jenis:

    • Jika jenis 'creditCard', Zod mengesahkan mengikut kekangan yang ditakrifkan dalam objek pertama.
    • Jika jenis 'paypal', ia hanya menyemak peraturan yang dipautkan ke objek PayPal.
    • Jika jenis 'bankTransfer', ia mengesahkan mengikut kriteria pemindahan bank.
  2. Pengesahan yang ketat :

    • Setiap jenis adalah bebas. Jika pengguna menyediakan jenis yang tidak sah atau meninggalkan medan yang diperlukan, Zod mencetuskan ralat tertentu.
  3. Kesederhanaan untuk Borang React Hook:

    • Skema membenarkan RHF menyesuaikan pengesahan secara dinamik mengikut medan jenis, memudahkan logik masuk borang.

**

Mengapa menggunakan discriminatedUnion di sini?

**

  1. Pemisahan tanggungjawab yang jelas
    • Setiap kaedah pembayaran peraturan khusus yang tidak boleh campur campur campur campur.
  2. Fleksibiliti
    • Membenarkan jenis baharu (cth. pembayaran baharu kaedah) untuk ditambah dengan mudah. jenis (contohnya, kaedah pembayaran baharu).
  3. Keselamatan
    • Memastikan bahawa sebarang nilai yang tidak sah dikesan di masa pengesahan.

**

Penyepaduan dengan Borang React Hook

**
React Hook Form memudahkan untuk mengurus borang sambil kekal berprestasi tinggi dan fleksibel. Begini cara untuk mengintegrasikan Zod dan RHF untuk mengesahkan borang berdasarkan discriminatedUnion.

import { useForm, SubmitHandler, FieldErrors } daripada 'react-hook-form';
import { zodResolver } daripada '@hookform/resolvers/zod';
import './payment.css';
import {
  PaymentMethodEnum,
  Skema kaedah pembayaran,
  PaymentMethodSchemaType,
} daripada '../validators/validate-payment-schema';

const Bayaran = () => {
  borang const = useForm<PaymentMethodSchemaType>({
    penyelesai: zodResolver(paymentMethodSchema()),
    defaultValues: {
      jenis: PaymentMethodEnum.CREDIT_CARD,
    },
  });

  const { register, formState, handleSubmit } = form;

  const { ralat } = formState;

  const paymentType = form.watch().type;

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

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

  const onSubmit: SubmitHandler<PaymentMethodSchemaType> = (data) => {
    console.log('data', data);
  };

  const PaymentTypeFormNode: React.ReactNode = (() => {
    suis (jenis pembayaran) {
      case PaymentMethodEnum.BANKTRANSFER:
        const bankTransferErrors = getErrorsByPaymentType(errors, paymentType);

        kembali (
          <div>
            <div className="form">
              <label>Nombor akaun</label>
              <masukan
                {...register('accountNomber')}
                placeholder="Masukkan nombor akaun anda"
              />
              {bankTransferErrors?.accountNumber?.message && (
                <span className="errormessage">
                  {bankTransferErrors.accountNumber.message}
                </span>
              )}
            </div>

            <div className="form">
              <label>Kod bank</label>
              <masukan
                {...daftar('Kod bank')}
                placeholder="Masukkan kod bank anda"
              />
              {bankTransferErrors?.bankCode?.message && (
                <span className="errormessage">
                  {bankTransferErrors.bankCode.message}
                </span>
              )}
            </div>
          </div>
        );

      case PaymentMethodEnum.CREDIT_CARD:
        const creditCardErrors = getErrorsByPaymentType(errors, paymentType);
        kembali (
          <div>
            <div className="form">
              <label>Nombor Kad</label>
              <masukan
                {...daftar('Nombor kad')}
                placeholder="Masukkan nombor kad anda"
              />
              {creditCardErrors?.cardNumber && (
                <span className="errormessage">
                  {creditCardErrors.cardNumber.message}
                </span>
              )}
            </div>

            <div className="form">
              <label>CVV</label>
              <masukan
                {...daftar('cvv')}
                placeholder="Masukkan kod pengesahan kad anda"
              />
              {creditCardErrors?.cvv && (
                <span className="errormessage">
                  {creditCardErrors.cvv.message}
                </span>
              )}
            </div>
          </div>
        );

      case PaymentMethodEnum.PAYPAL:
        const paypalErrors = getErrorsByPaymentType(errors, paymentType);
        kembali (
          <div className="form">
            <label>E-mel</label>
            <masukan
              type="e-mel"
              {...daftar('e-mel')}
              placeholder="Masukkan e-mel anda"
            />
            {paypalErrors?.email?.message && (
              <span className="errormessage">{paypalErrors.email.message}</span>
            )}
          </div>
        );

      lalai:
        buang Ralat baharu(
          'Ekhaustive Guard Error : received value' paymentType
        );
    }
  })();

  kembali (
    <form className="form-wrapper" onSubmit={handleSubmit(onSubmit)}>
      <div className="form">



<p>**</p>

<h2>
  
  
  Kesimpulan
</h2>

<p>**<br>
Jadi begitulah kawan-kawan. Saya harap anda mendapati artikel ini membantu. discriminatedUnion ialah jenis utiliti yang boleh digunakan dalam pelbagai cara. Jika anda fikir terdapat lebih banyak cara untuk menggunakan discriminatedUnion, sila beritahu saya dalam ulasan. Terima kasih kerana membaca artikel ini. Jumpa anda semua dalam artikel saya yang seterusnya?.</p>

<p>pautan permohonan ujian: <br>
https://stackblitz.com/edit/vitejs-vite-ppgw9zrb?file=src/pages/payments.tsx</p>


          

            
        
Salin selepas log masuk

Atas ialah kandungan terperinci Borang dinamik dengan discriminatedUnion dan React Hook Form. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:dev.to
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Artikel terbaru oleh pengarang
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan