Այս հոդվածը հովանավորվում է SurveyJS-ի կողմից Կա մի մտավոր մոդել, որը React ծրագրավորողների մեծամասնությունը կիսում է առանց այն բարձրաձայն քննարկելու: Այդ ձևերը միշտ ենթադրվում են, որ բաղադրիչներ են: Սա նշանակում է այնպիսի բուրգ, ինչպիսին է.
React Hook Form տեղական վիճակի համար (նվազագույն վերարտադրումներ, էրգոնոմիկ դաշտի գրանցում, հրամայական փոխազդեցություն): Zod վավերացման համար (մուտքագրման ճշգրտություն, սահմանների վավերացում, տիպի անվտանգ վերլուծություն): Արձագանքեք հարցումը backend-ի համար՝ ներկայացում, կրկնակի փորձեր, քեշավորում, սերվերի համաժամացում և այլն:
Եվ ձևերի ճնշող մեծամասնության համար՝ ձեր մուտքի էկրանները, ձեր կարգավորումների էջերը, ձեր CRUD մոդալները, սա իսկապես լավ է աշխատում: Յուրաքանչյուր կտոր կատարում է իր գործը, դրանք մաքուր են կազմում, և դուք կարող եք անցնել ձեր հավելվածի այն մասերին, որոնք իրականում տարբերում են ձեր արտադրանքը: Բայց մեկ-մեկ ձևը սկսում է կուտակել այնպիսի բաներ, ինչպիսիք են տեսանելիության կանոնները, որոնք կախված են ավելի վաղ պատասխաններից, կամ ստացված արժեքները, որոնք կասկադային են երեք դաշտերում: Միգուցե նույնիսկ ամբողջ էջերը, որոնք պետք է բաց թողնել կամ ցուցադրել՝ հիմնվելով ընթացիկ ընդհանուր տվյալների վրա: Դուք կառավարում եք առաջին պայմանականը useWatch-ի և inline ճյուղի միջոցով, ինչը լավ է: Հետո մեկ ուրիշը։ Այնուհետև դուք ձգտում եք superRefine-ին՝ կոդավորելու խաչաձեւ դաշտային կանոնները, որոնք ձեր Zod սխեման չի կարող արտահայտել սովորական ձևով: Այնուհետև քայլերի նավիգացիան սկսում է արտահոսել բիզնես տրամաբանությունից: Ինչ-որ պահի, դուք նայում եք, թե ինչ եք կառուցել և հասկանում, որ ձևն այլևս իրականում UI չէ: Դա ավելի շատ որոշումների գործընթաց է, և բաղադրիչ ծառը հենց այնտեղ է, որտեղ դուք այն պահել եք: Սա այն վայրն է, որտեղ ես կարծում եմ, որ React-ում ձևերի մտավոր մոդելը փչանում է, և դա իսկապես ոչ ոքի մեղավոր չէ: RHF + Zod ստեկը գերազանց է այն, ինչի համար նախատեսված է: Խնդիրն այն է, որ մենք հակված ենք շարունակել այն օգտագործել այն կետից, որտեղ դրա վերացականությունները համընկնում են խնդրի հետ, քանի որ այլընտրանքը պահանջում է բոլորովին այլ կերպ մտածել ձևերի մասին: Այս հոդվածը հենց այդ այլընտրանքի մասին է։ Դա ցույց տալու համար մենք երկու անգամ կկառուցենք ճիշտ նույն բազմաքայլ ձևը.
React Hook Form + Zod-ով միացված է React Query-ին` ներկայացնելու համար, SurveyJS-ով, որը ձևը վերաբերվում է որպես տվյալների՝ պարզ JSON սխեմայի, այլ ոչ թե բաղադրիչ ծառի:
Նույն պահանջները, նույն պայմանական տրամաբանությունը, նույն API զանգը վերջում: Այնուհետև մենք ճշգրիտ կնկարագրենք, թե ինչն է տեղափոխվել և ինչ մնացել, և կներկայացնենք գործնական միջոց՝ որոշելու համար, թե որ մոդելը պետք է օգտագործեք և երբ: Ձևը, որը մենք կառուցում ենք.
Այս ձևը կօգտագործի 4 քայլից բաղկացած հոսք. Քայլ 1. Մանրամասներ
Անունը (պարտադիր է), փոստ (պարտադիր, վավեր ձևաչափ):
Քայլ 2. Պատվիրել
Միավորի գինը, Քանակ, Հարկի դրույքաչափը, Ստացված: Ենթագումար, Հարկային, Ընդամենը.
Քայլ 3. Հաշիվ և հետադարձ կապ
Դուք ունեք հաշիվ: (Այո/Ոչ) Եթե Այո → օգտանուն + գաղտնաբառ, երկուսն էլ պարտադիր են: Եթե ոչ → 1-ին քայլում արդեն հավաքված էլ.
Գոհունակության վարկանիշ (1–5) Եթե ≥ 4 → հարցրեք «Ի՞նչն է ձեզ դուր եկել»: Եթե ≤ 2 → հարցրեք «Ի՞նչ կարող ենք բարելավել»:
Քայլ 4. Վերանայել
Հայտնվում է միայն, եթե ընդհանուր >= 100 Վերջնական ներկայացում.
Սա ծայրահեղություն չէ։ Բայց դա բավական է բացահայտելու ճարտարապետական տարբերությունները: Մաս 1. Բաղադրիչի վրա հիմնված (React Hook Form + Zod) Տեղադրում npm տեղադրել react-hook-form zod @hookform/resolvers @tanstack/react-query
Զոդի սխեման Սկսենք Զոդի սխեմայից, քանի որ սովորաբար հենց այստեղ է ձևավորվում ձևի ձևը: Առաջին երկու քայլերի համար՝ անձնական տվյալներ և պատվերի մուտքագրում, ամեն ինչ պարզ է՝ պահանջվող տողեր, թվեր նվազագույններով և թվով: Հետաքրքիրը սկսվում է այն ժամանակ, երբ փորձում ես արտահայտել պայմանական կանոնները։
ներմուծել { z } «zod»-ից;
արտահանում const formSchema = z.object({ firstName: z.string().min(1, «Պահանջվում է»), էլ. z.string().ընտրովի(), գաղտնաբառ՝ z.string().ընտրովի(), բավարարվածություն՝ z.number().min(1).max(5), positiveFeedback՝ z.string().optional(), բարելավումՀետադարձ կապ՝ z.string().ընտրովի(),}).superRefine((տվյալներ, {Afsda)=ha" (!data.username) {ctx.addIssue({ code: "custom", path. }
if (data.satisfaction >= 4 && !data.positiveFeedback) {ctx.addIssue({ կոդը՝ «custom», ուղի՝ [«positiveFeedback»], հաղորդագրություն՝ «Խնդրում ենք կիսվել այն, ինչ ձեզ դուր է եկել» }); }
if (data.satisfaction <= 2 && !data.improvementFeedback) {ctx.addIssue({ կոդը՝ «custom», path:["improvementFeedback"], հաղորդագրություն. «Խնդրում եմ, ասեք մեզ, թե ինչ բարելավենք» }); }});
արտահանման տեսակը FormData = z.infer
Ուշադրություն դարձրեք, որ օգտանունը և գաղտնաբառը մուտքագրվում են որպես ընտրովի(), չնայած դրանք պայմանականորեն պահանջվում են, քանի որ Zod-ի տիպի մակարդակի սխեման նկարագրում է օբյեկտի ձևը, այլ ոչ թե դաշտերի նշանակությունը կարգավորող կանոնները: Պայմանական պահանջը պետք է ապրի superRefine-ի ներսում, որն աշխատում է այն բանից հետո, երբ ձևը վավերացվում է և հասանելի է դառնում ամբողջական օբյեկտին: Այդ բաժանումը թերություն չէ. դա հենց այն է, ինչի համար նախատեսված է գործիքը. superRefine-ն այն տեղն է, որտեղ անցնում է խաչաձեւ դաշտային տրամաբանությունը, երբ այն չի կարող արտահայտվել հենց սխեմայի կառուցվածքում: Այստեղ հատկանշական է նաև այն, ինչ այս սխեման չի արտահայտում: Այն չունի էջերի հասկացություն, չկա հասկացություն, թե որ կետում որ դաշտերը տեսանելի են, և չկա նավիգացիա: Այդ ամենը կապրի մեկ այլ տեղ։ Ձևի բաղադրիչ
ներմուծում {useForm, useWatch } «react-hook-form»-ից;ներմուծում {zodResolver }-ից «@hookform/resolvers/zod»-ից;ներմուծում {useMutation }-ից «@tanstack/react-query»-ից;ներմուծում {useState, useMemo } «react»-ից;ներմուծում տիպը «FormDsche-ից», ներմուծում {formSchema-ից:
const STEPS = [«մանրամասներ», «պատվեր», «հաշիվ», «վերանայում»];
տեսակ OrderPayload = FormData & { subtotal: number; հարկ՝ համար; ընդհանուր՝ համարը };
արտահանման ֆունկցիա RHFMultiStepForm() {const [քայլ, setStep] = useState(0);
const mutation = useMutation({ mutationFn՝ async (վճարելի բեռ՝ OrderPayload) => { const res = await fetch("/api/orders", { մեթոդ՝ «ՓՈՍՏ», վերնագրեր՝ { "Content-Type": "application/json" }, մարմին՝ JSON.stringify(payload), }); եթե (!res.ok) նետել նոր Սխալ ("Չհաջողվեց ներկայացնել"); վերադարձնել res.json(); }, });
const { register, control, handleSubmit, formState: { errors }, } = useForm
վերադարձ (
);}Տես Գրիչ SurveyJS-03-RHF [forked] by sixthextinction: Այստեղ բավականին շատ բան է կատարվում, և արժե դանդաղել՝ նկատելու համար, թե որտեղ են ավարտվել իրադարձությունները:
Ստացված արժեքները՝ ենթատոտալ, հարկ, ընդհանուր, հաշվարկվում են բաղադրիչում useWatch-ի և useMemo-ի միջոցով, քանի որ դրանք կախված են կենդանի դաշտի արժեքներից, և դրանց համար այլ բնական տեղ չկա: Օգտվողի անվան, գաղտնաբառի, դրական արձագանքի և բարելավման հետադարձ կապի տեսանելիության կանոնները գործում են JSX-ում՝ որպես ներկառուցված պայմանականություններ: Քայլ բաց թողնելու տրամաբանությունը. վերանայման էջը հայտնվում է միայն այն դեպքում, երբ ընդհանուր >= 100-ը ներդրված է showSubmit փոփոխականում և 3-րդ քայլի ցուցադրման պայմանում: Նավիգացիան ինքնին պարզապես useState հաշվիչ է, որը մենք ձեռքով ավելացնում ենք: React Query-ն կարգավորում է կրկնակի փորձերը, քեշավորումը և անվավերությունը: Ձևը պարզապես անվանում է mutation.mutate վավերացված տվյալներով:
Սրանցից ոչ մեկն ինքնին սխալ չէ: Սա դեռևս իդիոմատիկ React է, և բաղադրիչը բավականին արդյունավետ է այն բանի շնորհիվ, թե ինչպես է RHF-ի մեկուսացումը վերարտադրվում: Բայց եթե սա հանձնեիք որևէ մեկին, ով այն չի գրել, և խնդրեք բացատրել, թե ինչ պայմաններում է հայտնվում վերանայման էջը, նա պետք է հետևի showSubmit-ի, քայլ 3-ի ցուցադրման պայմանի և նավի կոճակի տրամաբանության՝ երեք առանձին վայրերի միջոցով, որպեսզի վերակառուցի կանոն, որը կարող էր նշվել մեկ տողում: Ձևն աշխատում է, այո, բայց վարքագիծը որպես համակարգ իրականում ստուգելի չէ: Այն պետք է մտովի իրականացվի: Ավելի կարևոր է, որ այն փոխելը պահանջում է ինժեներական ներգրավվածություն: Նույնիսկ մի փոքր կսմթել, օրինակ՝ կարգավորելը, երբ հայտնվի վերանայման քայլը, նշանակում է խմբագրել բաղադրիչը, թարմացնել վավերացումը, բացել ձգման հարցումը, սպասել վերանայման և նորից տեղակայել: Մաս 2. սխեմայով պայմանավորված (SurveyJS) Հիմա եկեք կառուցենք նույն հոսքը՝ օգտագործելով սխեմա: Տեղադրում npm տեղադրել survey-core survey-react-ui @tanstack/react-query
Survey-core MIT-ի արտոնագրված պլատֆորմից անկախ գործարկման շարժիչը, որն ապահովում է SurveyJS-ի ձևերի արտապատկերումը. այն մասը, որը մեզ հետաքրքրում է այստեղ: Այն վերցնում է JSON սխեման, դրանից կառուցում է ներքին մոդել և մշակում է այն ամենը, ինչ այլ կերպ կբնակվեր ձեր React բաղադրիչում. տեսանելիության արտահայտությունների գնահատում, ստացված արժեքների հաշվարկ, էջի վիճակի կառավարում, վավերացման հետևում և որոշում, թե ինչ է նշանակում «լրիվ»՝ հաշվի առնելով, թե որ էջերն են իրականում ցուցադրվել:
Survey-react-ui UI / մատուցման շերտ, որը միացնում է այդ մոդելը React-ին: Դա, ըստ էության,
Միասին նրանք ձեզ տալիս են լիարժեք ֆունկցիոնալ, բազմաէջանոց ձևի գործարկման ժամանակ՝ առանց վերահսկողության հոսքի մեկ տող գրելու: Սխեմայի ձևաչափն ինքնին, ինչպես նախկինում ասվեց, պարզապես JSON է՝ առանց DSL կամ որևէ սեփականության: Դուք կարող եք ներդնել այն, ներմուծել այն ֆայլից, վերցնել այն API-ից կամ պահել այն տվյալների բազայի սյունակում և խոնավացնել այն գործարկման ժամանակ: Նույն ձևը, ինչպես տվյալները Ահա նույն ձևը, այս անգամ արտահայտված որպես JSON օբյեկտ: Սխեման սահմանում է ամեն ինչ՝ կառուցվածքը, վավերացումը, տեսանելիության կանոնները, ստացված հաշվարկները, էջի նավարկությունը, և այն հանձնում է մոդելին, որը գնահատում է այն գործարկման ժամանակ: Ահա թե ինչ տեսք ունի այն ամբողջությամբ.
արտահանում const surveySchema = { վերնագիր՝ «Պատվերի հոսք», showProgressBar՝ «վերև», էջեր՝ [ {անուն՝ «մանրամասներ», տարրեր՝ [ {typ՝ «text», անուն՝ «firstName», isRequired: true }, {typ՝ «text», անուն՝ «email», inputType՝ «email», isRequired: «email», isRequired: «email», validatorsIn: }] } ] }, {անուն՝ «պատվեր», տարրեր՝ [ {տեսակ՝ «տեքստ», անուն՝ «գին», inputType՝ «համար», defaultValue՝ 0 }, {type: «text», անուն՝ «quantity», inputType՝ «number», default Value՝ 1 }, {type: «tropdown»,անուն՝ «taxRate», defaultValue՝ 0.1, ընտրանքներ՝ [ {արժեք՝ 0.05, տեքստ՝ «5%» }, {արժեք՝ 0.1, տեքստ՝ «10%» }, {արժեք՝ 0.15, տեքստ՝ «15%» } ] }, {տեսակ՝ «արտահայտություն», անուն՝ «subtotal» արտահայտություն։ «արտահայտություն», անունը՝ «հարկ», արտահայտություն՝ «{subtotal} {taxRate}» }, {type: «expression», անուն՝ «total», արտահայտություն՝ «{subtotal} + {tax}» } ] }, {name: «account», տարրեր՝ [ { type: «radiogroup», name: «hasAccount]» «hasAccount», «text»: «username», visualIf: «{hasAccount} = 'Այո'», isRequired: true }, {type: "text", name: "password", inputType: "password", visualIf: "{hasAccount} = 'Yes'", is Required: true, վավերացնողներ՝ [{ type: "text", min] նիշ: տեսակ՝ «վարկանիշ», անուն՝ «բավարարվածություն», rateMin՝ 1, rateMax՝ 5 }, {տեսակ՝ «մեկնաբանություն», անուն՝ «positiveFeedback», visualIf: «{satisfaction} >= 4» }, {type: «մեկնաբանություն», անուն՝ «improvementFeedback», տեսանելիԵթե: «{satisfaction», «viewIf. տեսանելիԵթե՝ «{total} >= 100», տարրեր՝ [] } ]};
Համեմատեք սա RHF տարբերակի հետ մի պահ:
SuperRefine բլոկը, որը պայմանականորեն պահանջում էր օգտվողի անուն և գաղտնաբառ, չկա: visualIf. «{hasAccount} = «Այո»»-ի հետ միասին isRequired. true-ը լուծում է երկու մտահոգությունները միասին, հենց դաշտում, որտեղ դուք ակնկալում եք գտնել դրանք: UseWatch + useMemo շղթան, որը հաշվարկել է ենթագումարը, հարկը և ընդհանուր գումարը, փոխարինվում է երեք արտահայտությունների դաշտերով, որոնք հղում են անում միմյանց անունով: Վերանայման էջի պայմանը, որը RHF տարբերակում հնարավոր էր վերակառուցել միայն showSubmit-ի միջոցով՝ քայլ 3-ի ցուցադրման ճյուղի միջոցով: Եվ վերջապես, nav կոճակի տրամաբանությունը էջի օբյեկտի մեկ տեսանելի If հատկություն է:
Նույն տրամաբանությունն է այնտեղ. Պարզապես սխեման նրան տալիս է ապրելու տեղ, որտեղ այն տեսանելի է առանձին, այլ ոչ թե տարածվում է բաղադրիչի վրա: Նկատի ունեցեք նաև, որ սխեման օգտագործում է տիպը՝ «արտահայտություն» ենթագումարի, հարկերի և ընդհանուրի համար: Արտահայտությունը միայն կարդալու է և օգտագործվում է հիմնականում հաշվարկված արժեքները ցուցադրելու համար: SurveyJS-ն աջակցում է նաև տիպին՝ «html» ստատիկ բովանդակության համար, սակայն հաշվարկված արժեքների համար արտահայտությունը ճիշտ ընտրություն է: Հիմա React կողմի համար: Ներկայացում և ներկայացում Շատ պարզ. Միացնել onComplete ձեր API-ին նույն կերպ՝ useMutation-ի կամ պարզ բեռնման միջոցով.
ներմուծում {useState, useEffect, useRef } «react»-ից;ներմուծում {useMutation } «@tanstack/react-query»-ից;ներմուծում { Model } «survey-core»-ից;ներմուծում { Survey } «survey-react-ui»-ից;ներմուծում «survey-core/curvey-core»-ից:
արտահանման ֆունկցիա SurveyForm() {const [model] = useState(() => new Model(surveySchema));
const mutation = useMutation({ mutationFn: async (տվյալներ) => { const res = await fetch("/api/orders", { մեթոդ՝ «ՓՈՍՏ», վերնագրեր՝ { "Content-Type": "application/json" }, մարմին՝ JSON.stringify(տվյալներ), }); եթե (!res.ok) նետել նոր Սխալ ("Չհաջողվեց ներկայացնել"); վերադարձնել res.json(); }, });
const mutationRef = useRef(mutation); mutationRef.current = մուտացիա; useEffect(() => {const handler = (ուղարկիչ) => mutationRef.current.mutate(sender.data); model.onComplete.add(handler); return () => model.onComplete.remove(handler);}, [model]); // ref-ը խուսափում է մշակողի վերագրանցումից յուրաքանչյուր արտապատկերում (մուտացիայի օբյեկտի նույնականացումը փոխվում է)
վերադարձ (
<>
Տես Գրիչ SurveyJS-03-SurveyJS [forked] by sixthextinction:
onComplete-ը միանում է, երբ օգտատերը հասնում է վերջին տեսանելի էջի ավարտին: Այսպիսով, եթե ընդհանուր թիվը երբեք չի անցնում 100-ը, և վերանայման էջը բաց է թողնվում, այն դեռ ճիշտ է բացվում, քանի որ SurveyJS-ը գնահատում է տեսանելիությունը՝ նախքան որոշելը, թե ինչ է նշանակում «վերջին էջը»: Այնուհետև, sender.data-ն պարունակում է բոլոր պատասխանները, ինչպես նաև հաշվարկված արժեքները (ենթագումար, հարկ, ընդհանուր), որպես առաջին կարգի դաշտեր, ուստի API-ի օգտակար բեռնվածությունը նույնական է RHF տարբերակի ձեռքով հավաքված onSubmit-ում: ԱյնmutationRef օրինաչափությունն այն նույնն է, ինչին կարող եք հասնել ցանկացած վայրում, որտեղ ձեզ անհրաժեշտ է իրադարձությունների կայուն մշակող արժեքի նկատմամբ, որը փոխվում է յուրաքանչյուր արտապատկերման դեպքում, որի մասին SurveyJS-ին հատուկ ոչինչ չկա:
React բաղադրիչն այլևս չի պարունակում որևէ բիզնես տրամաբանություն։ Չկա useWatch, ոչ մի պայմանական JSX, ոչ մի քայլ հաշվիչ, ոչ useMemo շղթա, ոչ superRefine: React-ն անում է այն, ինչում իրականում լավ է. բաղադրիչի մատուցում և այն միացնելով API զանգին: Ի՞նչն է շարժվել Out Of React-ից:
Մտահոգություն RHF Stack SurveyJS Տեսանելիություն JSX մասնաճյուղեր տեսանելի Եթե Ստացված արժեքներ useWatch / useMemo արտահայտություն Խաչաձեւ դաշտային կանոններ գերզտել Սխեմայի պայմանները Նավիգացիա քայլ պետություն Էջը տեսանելի Եթե Կանոնների գտնվելու վայրը Բաշխված ֆայլերի միջև Կենտրոնացված սխեմայի մեջ
Այն, ինչ մնում է React-ում, դասավորությունն է, ոճավորումը, ներկայացման լարերը և հավելվածների ինտեգրումը, այսինքն՝ այն բաները, որոնց համար իրականում նախատեսված է React-ը: Մնացած ամեն ինչ տեղափոխվեց սխեմա, և քանի որ սխեման պարզապես JSON օբյեկտ է, այն կարող է պահվել տվյալների բազայում, տարբերակվել ձեր հավելվածի կոդից անկախ կամ խմբագրվել ներքին գործիքակազմի միջոցով՝ առանց տեղակայման պահանջի: Արտադրանքի կառավարիչը, ով պետք է փոխի վերանայման էջը գործարկող շեմը, կարող է դա անել առանց բաղադրիչին դիպչելու: Սա նշանակալի գործառնական տարբերություն է թիմերի համար, որտեղ ձևի վարքագիծը հաճախ զարգանում է և միշտ չէ, որ առաջնորդվում է ինժեներների կողմից: Ե՞րբ օգտագործել յուրաքանչյուր մոտեցում: Ահա մի լավ կանոն, որն աշխատում է ինձ համար. պատկերացրեք, որ ձևն ամբողջությամբ ջնջեք: Ի՞նչ կկորցնեիք:
Եթե դա էկրաններ են, դուք ցանկանում եք բաղադրիչի վրա հիմնված ձևեր: Եթե դա բիզնեսի տրամաբանությունն է, ինչպիսիք են շեմերը, ճյուղավորման կանոնները և պայմանական պահանջները, որոնք կոդավորում են իրական որոշումները, դուք ցանկանում եք սխեմայի շարժիչ:
Նմանապես, եթե ձեր ճանապարհին սպասվող փոփոխությունները հիմնականում վերաբերում են պիտակներին, դաշտերին և դասավորությանը, RHF-ը ձեզ լավ կծառայի: Եթե դրանք վերաբերում են պայմաններին, արդյունքներին և կանոններին, որոնք ձեր օպերացիան կամ իրավաբանական թիմը կարող է հարմարեցնել երեքշաբթի կեսօրից հետո՝ առանց տոմս ներկայացնելու, SurveyJS-ի սխեմայի մոդելն առավել ազնիվ է: Այս երկու մոտեցումներն իրականում միմյանց հետ մրցակցության մեջ չեն։ Նրանք անդրադառնում են խնդիրների տարբեր դասերի, և սխալը, որ արժե խուսափել, տրամաբանության ծանրության հետ վերացականությունը չհամապատասխանելն է՝ կանոնների համակարգը որպես բաղադրիչ վերաբերվել, քանի որ դա ծանոթ գործիք է, կամ հասնել քաղաքականության շարժիչի, քանի որ ձևը հասել է երեք քայլի և ձեռք է բերել պայմանական դաշտ: Այն ձևը, որը մենք ստեղծել ենք այստեղ, դիտավորյալ գտնվում է սահմանի մոտ, բավական բարդ, որպեսզի բացահայտի տարբերությունը, բայց ոչ այնքան ծայրահեղ, որ համեմատությունը կեղծված թվա: Իրական ձևերի մեծամասնությունը, որոնք անգործունակ են դարձել ձեր կոդերի բազայում, հավանաբար գտնվում են նույն սահմանի մոտ, և սովորաբար հարցն այն է, թե արդյոք որևէ մեկը նշել է, թե ինչ են դրանք իրականում: Օգտագործեք React Hook Form + Zod, երբ.
Ձևաթղթերը ուղղված են CRUD-ին. Տրամաբանությունը մակերեսային է և UI-ի վրա հիմնված; Ինժեներներին է պատկանում բոլոր վարքագիծը. Backend-ը մնում է ճշմարտության աղբյուրը:
Օգտագործեք SurveyJS, երբ.
Ձևաթղթերը կոդավորում են բիզնես որոշումները. Կանոնները զարգանում են անկախ UI-ից; Տրամաբանությունը պետք է լինի տեսանելի, լսվող կամ տարբերակված. Ոչ ինժեներները ազդում են վարքի վրա. Նույն ձևը պետք է գործարկվի մի քանի առջևի վրա: