دا مقاله د SurveyJS لخوا سپانسر شوې ده دلته یو ذهني ماډل شتون لري چې ډیری د عکس العمل پراختیا کونکي پرته له دې چې په لوړ غږ بحث وکړي شریکوي. دا فورمې تل باید اجزا وي. دا پدې مانا ده چې یو سټیک لکه:

د محلي دولت لپاره د عکس العمل هوک فورمه (لږ تر لږه بیا رینډر، د ایرګونومیک ساحې ثبت، لازمي تعامل). د اعتبار لپاره زوډ (د ننوتلو سموالی، د حد تایید، د ډول خوندي تجزیه). د شالید لپاره د عکس العمل عکس العمل: سپارل ، بیا هڅه کول ، کیچ کول ، د سرور ترکیب ، او داسې نور.

او د ډیری فورمو لپاره - ستاسو د ننوتلو سکرینونه، ستاسو د ترتیباتو پاڼې، ستاسو د CRUD موډلونه - دا واقعیا ښه کار کوي. هره ټوټه خپله دنده ترسره کوي، دوی په پاکه توګه ترکیب کوي، او تاسو کولی شئ د خپل غوښتنلیک برخو ته لاړ شئ چې واقعیا ستاسو محصول توپیر کوي. مګر هر یو په یو وخت کې، فورمه د شیانو راټولول پیل کوي لکه د لید قواعد چې په پخوانیو ځوابونو پورې اړه لري، یا ترلاسه شوي ارزښتونه چې د دریو برخو له لارې تیریږي. شاید حتی ټولې پاڼې چې باید پریښودل شي یا د چلولو مجموعې پراساس ښودل شوي. تاسو لومړی مشروط د UseWatch او انلاین څانګې سره اداره کوئ، کوم چې ښه دی. بیا بل. بیا تاسو د کراس فیلډ قواعد کوډ کولو لپاره سوپر ریفین ته ورسیږئ چې ستاسو د زوډ سکیما نشي کولی په نورمال ډول څرګند کړي. بیا، ګام نیویګیشن د سوداګرۍ منطق لیک پیل کوي. په ځینو وختونو کې، تاسو هغه څه وګورئ چې تاسو یې جوړ کړي او پوه شئ چې دا فورمه واقعیا UI نه ده. دا د پریکړې پروسه ډیره ده، او د برخې ونې یوازې هغه ځای دی چې تاسو یې د ذخیره کولو لپاره پیښ شوي. دا هغه ځای دی چې زه فکر کوم په عکس العمل کې د شکلونو لپاره ذهني ماډل ماتیږي ، او دا واقعیا د هیچا ګناه نه ده. د RHF + Zod سټیک د هغه څه لپاره خورا ښه دی چې د دې لپاره ډیزاین شوی و. مسله دا ده چې موږ د دې ټکي څخه تیریدو ته دوام ورکوو چیرې چې د دې خلاصون له ستونزې سره سمون لري ځکه چې بدیل په بشپړ ډول د فورمو په اړه مختلف فکر کولو ته اړتیا لري. دا مقاله د دې بدیل په اړه ده. د دې ښودلو لپاره، موږ به ورته ورته څو مرحلې فارم دوه ځله جوړ کړو:

د عکس العمل هوک فورمې سره + زوډ د سپارلو لپاره د عکس العمل پوښتنې ته واستول، د SurveyJS سره، کوم چې د ډیټا په توګه فورمه درملنه کوي - یو ساده JSON سکیما - د برخې ونې پرځای.

ورته اړتیاوې، ورته شرطي منطق، په پای کې ورته API کال. بیا به موږ په سمه توګه نقشه وکړو چې څه حرکت شوي او څه پاتې دي، او د دې پریکړه کولو لپاره یوه عملي لاره جوړه کړو چې کوم ماډل باید وکاروئ، او کله. هغه فورمه چې موږ یې جوړوو:

دا فورمه به د 4 مرحلې جریان کاروي: مرحله 1: توضیحات

لومړی نوم (اړین) بریښنالیک (اړین، باوري بڼه).

2 ګام: امر

د واحد قیمت، مقدار، د مالیاتو کچه، اخستل شوي: فرعي مجموعه مالیه، ټول.

3 ګام: حساب او فیډبیک

ایا تاسو حساب لرئ؟ (هو/نه) که هو → کارن-نوم + پټنوم، دواړه اړین دي. که نه وي → بریښنالیک دمخه په لومړي ګام کې راټول شوی.

د رضایت درجه (1-5) که چیرې ≥ 4 → وپوښتئ "څه مو خوښ کړل؟" که ≤ 2 → وپوښتئ چې "موږ څه ښه کولی شو؟"

4 ګام: بیاکتنه

یوازې ښکاره کیږي که چیرې ټولټال >= 100 وي وروستنۍ سپارنه.

دا افراط نه دی. مګر دا د معمارۍ توپیرونو څرګندولو لپاره کافي دی. برخه 1: د اجزاو چلول (د عکس العمل هک فورمه + زوډ) نصب کول npm انسټالول react-hook-form zod @hookform/resolvers @tanstack/react-query

زود سکیما راځئ چې د زوډ سکیما سره پیل وکړو، ځکه چې دا معمولا هغه ځای دی چې د فارم شکل رامینځته کیږي. د لومړیو دوو مرحلو لپاره - شخصي توضیحات او د ترتیب کولو معلومات - هرڅه سم دي: اړین تارونه، شمیرې لږ تر لږه، او یو اینوم. په زړه پورې برخه هغه وخت پیل کیږي کله چې تاسو د شرطي قواعدو څرګندولو هڅه وکړئ.

واردول {z } له "zod" څخه؛

د صادرولو کانسټ فارم سکیما = z.object({لومړی نوم: z.string().min(1، "اړین")، بریښنالیک: z.string().email("ناسلي بریښنالیک")، بیه: z.number().min(0)، مقدار: z.number().min(1)، د مالیې نرخ: z.number().min(1)، د مالیې نرخ: z.number(:")، . "نه"])، کارن-نوم: z.string().اختیاري()، پټنوم: z.string().optional()، اطمینان: z.number().min(1).max(5)، positive Feedback: z.string().optional() , improvement Feedback: z.string().optional(ef)، ct(fine) = (fine)) super = (data.hasAccount === "هو") { که (!data.username) { ctx.addIssue({ code: "custom", path: ["usenname"], message: "Required" }); ["پاسورډ"]، پیغام: "لږ تر لږه 6 حروف" } });

که (data.satisfaction>= 4 && !data.positiveFeedback) { ctx.addIssue({ code: "custom", path: ["positive Feedback"]، پیغام: "مهرباني وکړئ هغه څه شریک کړئ چې تاسو یې خوښوي" }); }

که (data.satisfaction <= 2 && !data.improvementFeedback) { ctx.addIssue({ کوډ: "کسټم"، لاره:["improvementFeedback"]، پیغام: "مهرباني وکړئ موږ ته ووایاست چې څه ښه کړو" }); }});

د صادراتو ډول FormData = z.infer;

په یاد ولرئ چې د کارونکي نوم او پټنوم د اختیاري () په توګه ټایپ شوي که څه هم دوی په مشروط ډول اړین دي ځکه چې د زوډ ډول کچې سکیما د څیز شکل بیانوي ، نه هغه مقررات چې اداره کوي کله چې ساحې مهمې وي. شرطي اړتیا باید د سوپر ریفین دننه ژوند وکړي، کوم چې د شکل تایید وروسته پرمخ ځي او بشپړ اعتراض ته لاسرسی لري. دا بېلتون کومه نیمګړتیا نه ده؛ دا یوازې هغه څه دي چې وسیله د دې لپاره ډیزاین شوې: سوپر ریفین هغه ځای دی چیرې چې د کراس فیلډ منطق ځي کله چې دا پخپله د سکیما جوړښت کې څرګند نشي. هغه څه چې دلته هم د پام وړ دي هغه څه دي چې دا سکیما نه څرګندوي. دا د مخونو هیڅ مفهوم نلري، هیڅ مفهوم نلري چې کوم ساحې په کوم ځای کې لیدل کیږي، او د نیویګیشن هیڅ مفهوم نلري. دا ټول به په بل ځای کې ژوند وکړي. د فورمې اجزا

وارد کړئ { useForm, useWatch } له "react-hook-form" څخه؛ وارد کړئ { zodResolver } له "@hookform/resolvers/zod" څخه؛ وارد کړئ { useMutation } له "@tanstack/react-query" څخه؛ وارد کړئ { useState, useMemo } له "react" څخه؛ وارد کړئ { useState, useMemo } له "react" څخه؛ د schema } فورمه وارد کړئ.

const STEPS = ["تفصیلات"، "حکم"، "حساب"، "بیاکتنه"]؛

ډول OrderPayload = FormData & { فرعي مجموعه: شمیره; مالیه: شمیره مجموعه: شمېره };

د صادرولو فنکشن RHFMultiStepForm() { const [step, setStep] = useState(0);

const mutation = استعمال تغیر ({ mutationFn: async (payload: OrderPayload) => { const res = د راوړلو انتظار وکړئ("/api/orders"، { طریقه: "POST" سرلیکونه: { "د منځپانګې ډول": "application/json" }, بدن: JSON.stringify(payload) }); که (!res.ok) نوې تېروتنه وغورځوي("په سپارلو کې پاتې راغلی")؛ بیرته راګرځئ res.json(); }، });

const { راجستر، کنټرول، سمبالول، فورمه: { تېروتنې }، } = استعمال فارم ({ حل کونکی: zodResolver(formSchema)، default Values: { قیمت: 0، مقدار: 1، د مالیې کچه: 0.1، اطمینان: 3، }}، اطمینان: 3، })؛ const price = useWatch({کنټرول، نوم: "قیمت" }); const quantity = useWatch({کنټرول، نوم: "مقدار" }); const taxRate = useWatch({ control, name: "taxRate" }); const hasAccount = useWatch({ control, name: "hasAccount" }); const satisfaction = useWatch({کنټرول، نوم: "اطمینان" }); const subtotal = useMemo(() => (قیمت؟ 0) * (مقدار ؟؟ 1)، [قیمت، مقدار]); const tax = useMemo(() => فرعي مجموعه * (د مالیاتو نرخ 0)، [فرعي مجموعه، د مالیې نرخ]); const total = useMemo(() => فرعي مجموعه + مالیه، [فرعي مجموعه، مالیه]); const onSubmit = (ډاټا: FormData) => mutation.mutate({...data, subtotal, tax, total }); const showSubmit = (قدم === 2 && ټول <100) || (مرحله === 3 او ټول >= 100)

بیرته ستنیدنه (

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

{مرحله === 1 && ( <> <انتخاب {...register("taxRate", {valuesNumber>}) value="0.05">5%

فرعي مجموعه: {subtotal
مالیه: {tax}
ټول: {total}
)}

{قدم === 2 && ( <>

{hasAccount === "هو" او& ( <> )}

{اطمینان>= 4 && (