ई लेख सर्वेक्षणजेएस द्वारा प्रायोजित अछि एकटा मानसिक मॉडल अछि जे बेसीतर रिएक्ट डेवलपर साझा करैत छथि बिना कहियो जोर-जोर स’ चर्चा केने. कि रूप सदिखन घटक मानल जाइत अछि । एकर मतलब अछि एकटा ढेर जेना:

स्थानीय राज्य (न्यूनतम पुनः प्रस्तुत करय वाला, एर्गोनॉमिक क्षेत्र पंजीकरण, अनिवार्य बातचीत) कें लेल रिएक्ट हुक फॉर्म. सत्यापन (इनपुट सहीता, सीमा सत्यापन, प्रकार-सुरक्षित पार्सिंग) क लेल ज़ोड. बैकएंड क लेल रिएक्ट क्वेरी: सबमिशन, पुनः प्रयास, कैशिंग, सर्वर सिंक, आओर एहि तरहक.

आरू फॉर्म केरऽ विशाल बहुमत लेली — आपकऽ लॉगिन स्क्रीन, आपकऽ सेटिंग्स पन्ना, आपकऽ सीआरयूडी मोडल — ई वास्तव म॑ अच्छा काम करै छै । प्रत्येक टुकड़ा अपनऽ काम करै छै, वू साफ-सुथरा रचना करै छै, आरू आप अपनऽ एप्लीकेशन केरऽ वू भागऽ प॑ आगू बढ़ी सकै छियै जे वास्तव म॑ आपकऽ उत्पाद क॑ अलग करै छै । लेकिन हर एक बेर कोनो फॉर्म दृश्यता नियम जैसनऽ चीजऽ के जमावड़ा शुरू करी दै छै जे पहिने के जवाबऽ प॑ निर्भर करै छै, या व्युत्पन्न मान जे तीन क्षेत्रऽ के माध्यम स॑ झरना होय जाय छै । शायद पूरा पन्ना सेहो जे छोड़ल जेबाक चाही वा रनिंग टोटल के आधार पर देखाओल जेबाक चाही। अहाँ पहिल कंडीशनल कए useWatch आओर इनलाइन शाखा क संग संभालैत छी, जे ठीक अछि. तखन दोसर। तखन अहाँ superRefine तक पहुँचि रहल छी जे क्रॉस-फील्ड नियम केँ एन्कोड करय जे अहाँक Zod स्कीमा सामान्य तरीका सँ व्यक्त नहि क’ सकैत अछि. तखन, स्टेप नेविगेशन बिजनेस लॉजिक लीक होबय लगैत अछि. कोनो समय, अहाँ जे बनौने छी से देखैत छी आ बुझैत छी जे आब फॉर्म वास्तव मे यूआई नहि अछि. ई निर्णय प्रक्रिया बेसी अछि, आ घटक गाछ ठीक ओतहि अछि जतय संयोगवश अहाँ एकरा संग्रहित केने रही. हमरा लगैत अछि जे रिएक्ट मे फॉर्म’क मानसिक मॉडल एतहि टूटि जाइत छैक, आ वास्तव मे एहि मे ककरो कोनो गलती नहि. आरएचएफ + ज़ोड स्टैक ओहि मे उत्कृष्ट अछि जे एकरा लेल डिजाइन कएल गेल छल । मुद्दा ई छै कि हम्में एकरऽ उपयोग वू बिन्दु स॑ आगू करी क॑ रखै के प्रवृत्ति रखै छियै जहाँ एकरऽ अमूर्तता समस्या स॑ मेल खाबै छै, कैन्हेंकि विकल्प लेली रूपऽ के बारे म॑ पूर्ण रूप स॑ सोचै के अलग तरीका के जरूरत छै । ई लेख ओहि विकल्पक विषय मे अछि। एकरा देखाबय लेल हम ठीक एकहि मल्टी-स्टेप फॉर्म के दू बेर बना लेब:

सबमिशन के लेल रिएक्ट हुक फॉर्म + ज़ोड के रिएक्ट क्वेरी के तार के संग, SurveyJS कें साथ, जे कोनों फॉर्म कें डेटा कें रूप मे मानयत छै — एकटा सरल JSON स्कीमा — कें बजाय एकटा घटक वृक्ष कें.

एकहि आवश्यकता, एकहि सशर्त तर्क, अंत मे एकहि एपीआई कॉल। तखन हम ठीक-ठीक नक्शा बना लेब जे की हिलल आ की रहल, आ एकटा व्यावहारिक तरीका बिछाएब जे अहाँ कोन मॉडलक उपयोग करबाक चाही, आ कहिया. हम जे फॉर्म बना रहल छी:

एहि फॉर्म मे 4-चरणीय प्रवाहक उपयोग होयत: चरण 1: विवरण

प्रथम नाम (आवश्यक), . ईमेल (आवश्यक, वैध प्रारूप)।

चरण 2: आदेश

इकाई मूल्य, 1999। मात्रा, 1999। कर दर, 1999। व्युत्पन्न : १. उपकुल, 1999। कर, 1999। कुल।

चरण 3: खाता एवं प्रतिक्रिया

अहाँक खाता अछि की? (हाँ/नहि) २. यदि हाँ → उपयोगकर्ता नाम + पासवर्ड, दुनू आवश्यक. यदि नहि → ईमेल चरण 1 मे पहिने सं एकत्रित भ गेल अछि.

संतुष्टि रेटिंग (1–5) 1.1. यदि ≥ 4 → पूछू “अहाँ केँ की नीक लागल?” यदि ≤ 2 → पूछू “हम की सुधार क सकैत छी?”

चरण 4: समीक्षा करू

केवल तखन प्रकट होइत अछि जखन कुल >= 100 अछि अंतिम प्रस्तुति।

ई चरम नहि अछि। मुदा वास्तुकला के अंतर के उजागर करय लेल काफी अछि. भाग 1: घटक-संचालित (रिएक्ट हुक फॉर्म + ज़ोड) स्थापना npm react-hook-form zod @hookform/resolvers @tanstack/react-query इंस्टॉल करू

ज़ोड योजना शुरुआत ज़ोड स्कीमा स’ करी, कारण प्रायः ओतहि रूपक आकार स्थापित भ’ जाइत अछि । पहिल दू चरणक कें लेल — व्यक्तिगत विवरण आ आदेश इनपुट — सब किछु सीधा छै: आवश्यक स्ट्रिंग, न्यूनतम कें साथ संख्या, आ एकटा enum. रोचक भाग तखन शुरू होइत अछि जखन अहाँ सशर्त नियम व्यक्त करबाक प्रयास करैत छी ।

"zod" से आयात { z };

निर्यात const formSchema = z.object ({ firstName: z.string ().min (1, "आवश्यक"), ईमेल: z.string ().email ("अवैध ईमेल"), मूल्य: z.number ().min (0), मात्रा: z.number ().min (1), taxRate: z.number (), hasAccount: z.enum (["हाँ", "कोई"]), उपयोगकर्ता नाम: z.string ().वैकल्पिक (), पासवर्ड: z.string ().वैकल्पिक (), संतुष्टि: z.number ().min (1). अधिकतम (5), सकारात्मकप्रतिक्रिया: z.string ().वैकल्पिक (), सुधारप्रतिक्रिया: z.string ().वैकल्पिक (),}).superRefine ((डेटा, ctx) => { अगर (डेटा.hasAccount === "हाँ") { अगर (! डेटा.उपयोगकर्ता नाम) { ctx.addIssue ({ कोड: "कस्टम", पथ: ["उपयोगकर्ता नाम"], संदेश: "आवश्यक" }); } if (! डेटा.पासवर्ड || डेटा.पासवर्ड.लंबाई < 6) { ctx.addIssue ({ कोड: "कस्टम", पथ: ["पासवर्ड"], संदेश: "Min 6 वर्ण" });

if (data.satisfaction >= 4 && !data.positiveFeedback) { ctx.addIssue({ कोड: "कस्टम", पथ: ["positiveFeedback"], message: "कृपया साझा करू जे अहाँकेँ नीक लागल" }); } .

if (डेटा.संतुष्टि <= 2 && !डेटा.सुधारप्रतिक्रिया) { ctx.addIssue ({ कोड: "कस्टम", पथ:["improvementFeedback"], message: "कृपया बताउ जे की सुधार करबाक चाही" }); }});

निर्यात प्रकार FormData = z.infer ;

ध्यान दिअ जे यूजरनेम आओर पासवर्ड वैकल्पिक() के रूप मे टाइप कएल गेल अछि भले ही ई सशर्त रूप सं आवश्यक हो किएक त’ Zod के टाइप-स्तर स्कीमा ऑब्जेक्ट के आकार के वर्णन करैत अछि, नहि कि नियम के जे फील्ड कखन मायने रखैत अछि. सशर्त आवश्यकता क॑ superRefine के अंदर रहना छै, जे आकृति क॑ मान्य करला के बाद चलै छै आरू ओकरा पूरा ऑब्जेक्ट तलक पहुँच छै । ओ विरह कोनो दोष नहि; ई बस वू छै जेकरा लेली टूल डिजाइन करलऽ गेलऽ छै: superRefine वू जगह छै जहाँ क्रॉस-फील्ड लॉजिक जाय छै जब॑ ओकरा खुद स्कीमा संरचना म॑ व्यक्त नै करलऽ जाब॑ सकै छै. एत’ जे बात सेहो उल्लेखनीय अछि से ई जे ई योजना की नहि व्यक्त करैत अछि. एकरऽ पन्ना केरऽ कोय अवधारणा नै छै, कोन क्षेत्र कोन बिन्दु पर दिखाई दै छै, आरू नेविगेशन केरऽ कोय अवधारणा नै छै । ओ सबटा कतहु आन ठाम रहत। फॉर्म घटक

आयात { useForm, useWatch } से "react-hook-form";import { zodResolver } से "@hookform/resolvers/zod";import { useMutation } से "@tanstack/react-query";import { useState, useMemo } से "react";आयात { formSchema, type FormData } से "./schema";

const STEPS = ["विवरण", "क्रम", "खाता", "समीक्षा"];

प्रकार OrderPayload = FormData & { उपकुल: संख्या; कर: संख्या; कुल: संख्या };

निर्यात फ़ंक्शन RHFMultiStepForm () { const [चरण, setStep] = useState (0);

const उत्परिवर्तन = उपयोगMutation ({ mutationFn: async (पेलोड: ऑर्डरपेलोड) => { const res = प्रतीक्षा fetch ("/ api / आदेश", { विधि: "पोस्ट",। headers: { "सामग्री-प्रकार": "अनुप्रयोग/json" }, शरीर: JSON.stringify (पेलोड), }); if (!res.ok) throw new Error ("सबमिट करबा मे विफल"); return res.json (); }, ८. });

const { रजिस्टर, नियंत्रण, handleSubmit, formState: { त्रुटियाँ }, } = useForm ({ समाधानकर्ता: zodResolver (formSchema), defaultValues: { कीमत: 0, मात्रा: 1, कर दर: 0.1, संतुष्टि: 3, hasAccount: "कोई", }, }); const मूल्य = useWatch ({ नियंत्रण, नाम: "मूल्य" }); const मात्रा = useWatch ({ नियंत्रण, नाम: "मात्रा" }); const taxRate = useWatch ({ नियंत्रण, नाम: "कर दर" }); const hasAccount = useWatch ({ नियंत्रण, नाम: "खाता है" }); const संतुष्टि = useWatch ({ नियंत्रण, नाम: "संतुष्टि" }); const उपकुल = useMemo (() => (मूल्य ?? 0) * (मात्रा ?? 1), [मूल्य, मात्रा]); const कर = useMemo (() => उपकुल * (कर दर ?? 0), [उपकुल, कर दर]); const कुल = useMemo (() => उपकुल + कर, [उपकुल, कर]); const onSubmit = (डेटा: FormData) => mutation.mutate ({ ... डेटा, उपकुल, कर, कुल }); const showSubmit = (चरण === 2 && कुल < 100) || (चरण === 3 && कुल >= 100)

return (

{step === 0 && ( <> )}

{step === 1 && ( <> <इनपुट प्रकार="संख्या" {...पंजीकरण ("मूल्य", { valueAsNumber: true })} />

उपकुल: {उपकुल}
कर: {कर}
कुल: {कुल}
)}

{step === 2 && ( <>

{hasAccount === "हाँ" && ( <> )}

{संतुष्टि >= 4 && (