આ લેખ SurveyJS દ્વારા પ્રાયોજિત છે એક માનસિક મોડલ છે જે મોટા ભાગના React ડેવલપર્સ તેને ક્યારેય મોટેથી ચર્ચા કર્યા વિના શેર કરે છે. તે સ્વરૂપો હંમેશા ઘટકો હોવાનું માનવામાં આવે છે. આનો અર્થ એક સ્ટેક છે જેમ કે:

સ્થાનિક રાજ્ય માટે પ્રતિક્રિયા હૂક ફોર્મ (ન્યૂનતમ રી-રેન્ડર, અર્ગનોમિક ક્ષેત્ર નોંધણી, આવશ્યક ક્રિયાપ્રતિક્રિયા). માન્યતા માટે Zod (ઇનપુટ શુદ્ધતા, સીમા માન્યતા, પ્રકાર-સલામત પદચ્છેદન). બેકએન્ડ માટે પ્રતિક્રિયા ક્વેરી: સબમિશન, ફરીથી પ્રયાસો, કેશીંગ, સર્વર સમન્વયન, અને તેથી વધુ.

અને મોટાભાગના સ્વરૂપો માટે — તમારી લોગિન સ્ક્રીન, તમારા સેટિંગ્સ પૃષ્ઠો, તમારા CRUD મોડલ્સ — આ ખરેખર સારી રીતે કામ કરે છે. દરેક ભાગ તેનું કામ કરે છે, તેઓ સ્વચ્છ રીતે કંપોઝ કરે છે, અને તમે તમારી એપ્લિકેશનના ભાગો પર આગળ વધી શકો છો જે ખરેખર તમારા ઉત્પાદનને અલગ પાડે છે. પરંતુ દરેક સમયે, એક ફોર્મ દૃશ્યતા નિયમો જેવી વસ્તુઓ એકઠા કરવાનું શરૂ કરે છે જે અગાઉના જવાબો પર આધાર રાખે છે, અથવા વ્યુત્પન્ન મૂલ્યો કે જે ત્રણ ક્ષેત્રોમાંથી પસાર થાય છે. કદાચ આખા પૃષ્ઠો પણ કે જે ચાલતા કુલના આધારે છોડવા અથવા બતાવવા જોઈએ. તમે યુઝવૉચ અને ઇનલાઇન શાખા સાથે પ્રથમ શરતી સંભાળો છો, જે સારું છે. પછી બીજું. પછી તમે ક્રોસ-ફિલ્ડ નિયમોને એન્કોડ કરવા માટે સુપરરિફાઇન પર પહોંચી રહ્યાં છો કે જે તમારી Zod સ્કીમા સામાન્ય રીતે વ્યક્ત કરી શકતી નથી. પછી, સ્ટેપ નેવિગેશન બિઝનેસ લોજીક લીક કરવાનું શરૂ કરે છે. અમુક સમયે, તમે જે બનાવ્યું છે તે જુઓ અને સમજો કે ફોર્મ હવે ખરેખર UI નથી. તે એક નિર્ણય પ્રક્રિયા છે, અને ઘટક વૃક્ષ તે જ છે જ્યાં તમે તેને સંગ્રહિત કરવાનું થયું. આ તે છે જ્યાં મને લાગે છે કે પ્રતિક્રિયામાં સ્વરૂપો માટેનું માનસિક મોડેલ તૂટી જાય છે, અને તે ખરેખર કોઈની ભૂલ નથી. RHF + Zod સ્ટેક તેના માટે ડિઝાઇન કરવામાં આવ્યું હતું તે માટે ઉત્તમ છે. મુદ્દો એ છે કે અમે તેનો ઉપયોગ તે બિંદુથી આગળ ચાલુ રાખવાનું વલણ ધરાવીએ છીએ જ્યાં તેના અમૂર્તતા સમસ્યા સાથે મેળ ખાય છે કારણ કે વૈકલ્પિકને સંપૂર્ણપણે સ્વરૂપો વિશે વિચારવાની અલગ રીતની જરૂર છે. આ લેખ તે વિકલ્પ વિશે છે. આ બતાવવા માટે, અમે ચોક્કસ સમાન મલ્ટિ-સ્ટેપ ફોર્મ બે વાર બનાવીશું:

સબમિશન માટે પ્રતિક્રિયા ક્વેરી માટે રીએક્ટ હૂક ફોર્મ + Zod વાયર સાથે, SurveyJS સાથે, જે ફોર્મને ડેટા તરીકે ગણે છે — એક સરળ JSON સ્કીમા — એક ઘટક વૃક્ષને બદલે.

સમાન જરૂરિયાતો, સમાન શરતી તર્ક, અંતે સમાન API કૉલ. પછી અમે બરાબર શું ખસેડ્યું અને શું રહ્યું તેનો નકશો બનાવીશું અને તમારે કયા મોડલનો અને ક્યારે ઉપયોગ કરવો જોઈએ તે નક્કી કરવા માટે એક વ્યવહારુ રીત તૈયાર કરીશું. અમે જે ફોર્મ બનાવી રહ્યા છીએ:

આ ફોર્મ 4-પગલાંના પ્રવાહનો ઉપયોગ કરશે: પગલું 1: વિગતો

પ્રથમ નામ (જરૂરી), ઇમેઇલ (જરૂરી, માન્ય ફોર્મેટ).

પગલું 2: ઓર્ડર

એકમની કિંમત, જથ્થો, કર દર, વ્યુત્પન્ન: પેટાટોટલ, કર, કુલ.

પગલું 3: એકાઉન્ટ અને પ્રતિસાદ

શું તમારી પાસે એકાઉન્ટ છે? (હા/ના) જો હા → વપરાશકર્તા નામ + પાસવર્ડ, બંને જરૂરી છે. જો ના હોય તો → ઈમેઈલ પહેલાથી જ સ્ટેપ 1 માં એકત્રિત કરેલ છે.

સંતોષ રેટિંગ (1-5) જો ≥ 4 → પૂછે કે "તમને શું ગમ્યું?" જો ≤ 2 → પૂછે કે "આપણે શું સુધારી શકીએ?"

પગલું 4: સમીક્ષા કરો

જો કુલ >= 100 હોય તો જ દેખાય છે અંતિમ સબમિશન.

આ આત્યંતિક નથી. પરંતુ તે આર્કિટેક્ચરલ તફાવતોને છતી કરવા માટે પૂરતું છે. ભાગ 1: ઘટક-સંચાલિત (પ્રતિક્રિયા હૂક ફોર્મ + Zod) સ્થાપન npm install react-hook-form zod @hookform/resolvers @tanstack/react-query

ઝોડ સ્કીમા ચાલો Zod સ્કીમાથી શરૂઆત કરીએ, કારણ કે સામાન્ય રીતે તે જ જગ્યાએ ફોર્મનો આકાર સ્થાપિત થાય છે. પ્રથમ બે પગલાઓ માટે - વ્યક્તિગત વિગતો અને ઓર્ડર ઇનપુટ્સ - બધું જ સરળ છે: જરૂરી શબ્દમાળાઓ, ન્યૂનતમ સાથે સંખ્યાઓ અને એક એનમ. જ્યારે તમે શરતી નિયમોને વ્યક્ત કરવાનો પ્રયાસ કરો છો ત્યારે રસપ્રદ ભાગ શરૂ થાય છે.

"zod" માંથી { z } આયાત કરો;

export const formSchema = z.object({ firstName: z.string().min(1, "Required"), email: z.string().email("Invalid email"), કિંમત: z.number().min(0), quantity: z.number().min(1), tax Rate: z.number().min(1), tax Rate: z.number(", "જરૂરી"), છે. "ના"]), વપરાશકર્તાનામ: z.string().optional(), password: z.string().optional(), satisfaction: z.number().min(1).max(5), positive Feedback: z.string().optional(), improvementfeedback: z.string().optional(ef), ine (fine) = ( ct }) super = (data.hasAccount === "હા") { if (!data.username) { ctx.addIssue({ code: "custom", path: ["username"], message: "Required" }); } if (!data.password || data.password.length x. 6. cuss: "code: {addI) ["પાસવર્ડ"], સંદેશ: "ન્યૂનતમ 6 અક્ષરો" } });

જો (data.satisfaction >= 4 && !data.positiveFeedback) { ctx.addIssue({ code: "custom", path: ["positiveFeedback"], સંદેશ: "કૃપા કરીને તમને જે ગમ્યું તે શેર કરો" }); }

જો (data.satisfaction <= 2 && !data.improvementFeedback) { ctx.addIssue({ કોડ: "કસ્ટમ", પાથ:["improvementfeedback"], સંદેશ: "કૃપા કરીને અમને જણાવો કે શું સુધારવું છે" }); }});

નિકાસ પ્રકાર FormData = z.infer;

નોંધ લો કે વપરાશકર્તાનામ અને પાસવર્ડને વૈકલ્પિક() તરીકે ટાઈપ કરવામાં આવ્યા છે, તેમ છતાં તેઓ શરતી રીતે જરૂરી છે કારણ કે Zod ની પ્રકાર-સ્તરની સ્કીમા ઑબ્જેક્ટના આકારનું વર્ણન કરે છે, જ્યારે ફીલ્ડ્સ મહત્વના હોય ત્યારે નિયમન કરતા નિયમોનું નહીં. શરતી જરૂરિયાત સુપરરિફાઇનની અંદર રહે છે, જે આકાર માન્ય થયા પછી ચાલે છે અને સંપૂર્ણ ઑબ્જેક્ટની ઍક્સેસ ધરાવે છે. એ વિચ્છેદ એ દોષ નથી; તે ફક્ત તે જ છે જેના માટે ટૂલ ડિઝાઇન કરવામાં આવ્યું છે: સુપરરિફાઇન તે છે જ્યાં ક્રોસ-ફીલ્ડ લોજિક જાય છે જ્યારે તે સ્કીમા સ્ટ્રક્ચરમાં જ વ્યક્ત કરી શકાતું નથી. અહીં જે નોંધપાત્ર છે તે એ છે કે આ સ્કીમા શું વ્યક્ત કરતી નથી. તેમાં પૃષ્ઠોનો કોઈ ખ્યાલ નથી, કયા ક્ષેત્રો કયા બિંદુએ દૃશ્યમાન છે તેનો કોઈ ખ્યાલ નથી, અને નેવિગેશનનો કોઈ ખ્યાલ નથી. તે બધા બીજે ક્યાંક જીવશે. ફોર્મ ઘટક

"react-hook-form" માંથી { useForm, useWatch } આયાત કરો; "@hookform/resolvers/zod" માંથી { zodResolver } આયાત કરો; "@tanstack/react-query" માંથી { useMutation } આયાત કરો; "react" માંથી { useState, useMemo } આયાત કરો; "react" માંથી આયાત કરો, "માતા/માટે" ફોર્મ માંથી આયાત કરો.

const STEPS = ["વિગતો", "ઓર્ડર", "એકાઉન્ટ", "સમીક્ષા"];

પ્રકાર OrderPayload = FormData & { ઉપટોટલ: સંખ્યા; કર: નંબર; કુલ: સંખ્યા };

નિકાસ કાર્ય RHFMultiStepForm() { const [step, setStep] = useState(0);

const mutation = useMutation({ mutationFn: async (payload: OrderPayload) => { const res = લાવવાની રાહ જુઓ("/api/orders", { પદ્ધતિ: "પોસ્ટ", હેડર્સ: { "સામગ્રી-પ્રકાર": "એપ્લિકેશન/જેસન" }, મુખ્ય ભાગ: JSON.stringify(પેલોડ), }); જો (!res.ok) નવી ભૂલ ફેંકી દે ("સબમિટ કરવામાં નિષ્ફળ"); પરત res.json(); }, });

const { રજીસ્ટર, કંટ્રોલ, હેન્ડલ સબમિટ, ફોર્મસ્ટેટ: { ભૂલો }, } = useForm({ રિઝોલ્વર: zodResolver(formSchema), ડિફોલ્ટ મૂલ્યો: { કિંમત: 0, જથ્થો: 1, કર દર: 0.1, સંતોષ: "3,}}; const price = useWatch({ control, name: "price" }); const quantity = useWatch({ control, name: "quantity" }); const taxRate = useWatch({ control, name: "taxRate" }); const hasAccount = useWatch({ નિયંત્રણ, નામ: "hasAccount" }); const satisfaction = useWatch({ નિયંત્રણ, નામ: "સંતોષ" }); const subtotal = useMemo(() => (કિંમત ?? 0) * (જથ્થા ?? 1), [કિંમત, જથ્થો]); const tax = useMemo(() => સબટોટલ * (ટેક્સરેટ ?? 0), [સબટોટલ, ટેક્સરેટ]); const total = useMemo(() => સબટોટલ + ટેક્સ, [પેટાટોટલ, ટેક્સ]); const onSubmit = (ડેટા: ફોર્મડેટા) => mutation.mutate({ ...data, subtotal, tax, total }); const showSubmit = (પગલું === 2 && કુલ < 100) || (પગલું === 3 && કુલ >= 100)

પરત કરો (

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

{પગલું === 1 && ( <> <પસંદ કરો {...register("taxRate", {option}}) value="0.05">5%

સબટોટલ: {subtotal}
Tax: {tax}
કુલ: {total}
)}

{પગલું === 2 && ( <>

{hasAccount === "હા" && ( <> <ઇનપુટ {...register("username")} placeholder="Username" /> )}

{સંતોષ >= 4 && (