Makala haya yamefadhiliwa na SurveyJS Kuna mtindo wa kiakili ambao watengenezaji wengi wa React hushiriki bila hata kuujadili kwa sauti. Fomu hizo daima zinatakiwa kuwa vipengele. Hii inamaanisha mkusanyiko kama:
React Hook Form kwa jimbo la karibu (re-renders ndogo, usajili wa uwanja wa ergonomic, mwingiliano wa lazima). Zod kwa uthibitisho (usahihi wa pembejeo, uthibitishaji wa mipaka, uchanganuzi wa aina-salama). React Query kwa backend: kuwasilisha, kujaribu tena, akiba, kusawazisha server, na kadhalika.
Na kwa idadi kubwa ya aina - skrini zako za kuingia, kurasa zako za mipangilio, muundo wako wa CRUD - hii inafanya kazi vizuri sana. Kila kipande hufanya kazi yake, wanatunga kwa usafi, na unaweza kuendelea na sehemu za programu yako ambazo hutofautisha bidhaa yako. Lakini kila baada ya muda fulani, fomu huanza kukusanya vitu kama vile sheria za mwonekano ambazo zinategemea majibu ya awali, au maadili yanayotokana ambayo hupitia sehemu tatu. Labda hata kurasa zote ambazo zinapaswa kurukwa au kuonyeshwa kulingana na jumla inayoendeshwa. Unashughulikia masharti ya kwanza na useWatch na tawi la ndani, ambayo ni sawa. Kisha mwingine. Kisha unatafuta superRefine ili kusimba sheria za sehemu mbalimbali ambazo utaratibu wako wa Zod hauwezi kueleza kwa njia ya kawaida. Kisha, urambazaji wa hatua huanza kuvuja mantiki ya biashara. Wakati fulani, unatazama ulichounda na kugundua kuwa fomu hiyo si UI tena. Ni zaidi ya mchakato wa uamuzi, na mti wa sehemu ni mahali ambapo ulifanyika kuihifadhi. Hapa ndipo nadhani mtindo wa kiakili wa fomu katika React huvunjika, na kwa kweli hakuna kosa la mtu yeyote. Rafu ya RHF + Zod ni bora kwa kile iliundwa. Suala ni kwamba huwa tunaendelea kuitumia kupita mahali ambapo vifupisho vyake vinalingana na shida kwa sababu njia mbadala inahitaji njia tofauti ya kufikiria juu ya fomu kabisa. Makala hii inahusu mbadala huo. Ili kuonyesha hili, tutaunda fomu sawa ya hatua nyingi mara mbili:
Na Fomu ya React Hook + Zod iliyounganishwa ili Kujibu Hoja kwa uwasilishaji, Na SurveyJS, ambayo huchukulia fomu kama data - schema rahisi ya JSON - badala ya mti wa sehemu.
Mahitaji sawa, mantiki sawa ya masharti, simu sawa ya API mwishoni. Kisha tutapanga ramani ni nini hasa kilichosogezwa na kilichobaki, na kuweka njia ya vitendo ya kuamua ni mtindo gani unapaswa kutumia, na wakati gani. Fomu tunayotengeneza:
Fomu hii itatumia mtiririko wa hatua 4: Hatua ya 1: Maelezo
Jina la kwanza (linahitajika), Barua pepe (inahitajika, umbizo halali).
Hatua ya 2: Agizo
Bei ya kitengo, Kiasi, Kiwango cha ushuru, Imetolewa: Jumla ndogo, Kodi, Jumla.
Hatua ya 3: Akaunti na Maoni
Je, una akaunti? (Ndiyo/Hapana) Ikiwa Ndiyo → jina la mtumiaji + nenosiri, zote zinahitajika. Ikiwa Hapana → barua pepe tayari imekusanywa katika hatua ya 1.
Ukadiriaji wa kuridhika (1–5) Ikiwa ≥ 4 → uliza "Ulipenda nini?" Ikiwa ≤ 2 → uliza "Tunaweza kuboresha nini?"
Hatua ya 4: Kagua
Inaonekana tu ikiwa jumla >= 100 Uwasilishaji wa mwisho.
Hii sio kali. Lakini inatosha kufichua tofauti za usanifu. Sehemu ya 1: Inayoendeshwa na Kipengele (Aina ya React Hook + Zod) Ufungaji npm sakinisha react-hook-form zod @hookform/resolvers @tanstack/react-query
Zod Schema Hebu tuanze na schema ya Zod, kwa sababu ni kawaida ambapo sura ya fomu huanzishwa. Kwa hatua mbili za kwanza - maelezo ya kibinafsi na pembejeo za kuagiza - kila kitu ni moja kwa moja: mifuatano inayohitajika, nambari zilizo na kiwango cha chini, na enum. Sehemu ya kuvutia huanza unapojaribu kueleza sheria za masharti.
kuagiza {z } kutoka "zod";
export const formSchema = z.object({ firstName: z.string().min(1, "Inahitajika"), barua pepe: z.string().barua pepe("Barua pepe batili"), bei: z.number().min(0), kiasi: z.number().min(1), taxRate: z.number(), ina "Yescount:Acnum" z.string().hiari(), nenosiri: z.string().hiari(), kuridhika: z.number().min(1).max(5), positiveFeedback: z.string().optional(), improvementFeedback: z.string().optional(),}).superRefine((data, ctx) => { if (data) =Yeus =Yeus =Yeus. {ctx.addIssue({code: "desturi", njia: ["jina la mtumiaji"], ujumbe: "Inahitajika" }} ikiwa (!data.password || data.password.length < 6) { ctx.addIssue({code: "custom", path: ["password"]), herufi: "}}};
ikiwa (data.satisfaction >= 4 && !data.positiveFeedback) {ctx.addIssue({code: "custom", path: ["positiveFeedback"], ujumbe: "Tafadhali shiriki ulichopenda" }); }
ikiwa (data.satisfaction <= 2 && !data.improvementFeedback) {ctx.addIssue({code: "custom", path:["improvementFeedback"], ujumbe: "Tafadhali tuambie la kuboresha" }); }});
aina ya kuuza nje FormData = z.infer
Tambua kuwa jina la mtumiaji na nenosiri zimechapishwa kama hiari() ingawa zinahitajika kwa masharti kwa sababu taratibu za kiwango cha aina za Zod hufafanua umbo la kitu, si sheria zinazotawala wakati sehemu ni muhimu. Sharti la masharti lazima liishi ndani ya superRefine, ambayo huendesha baada ya umbo kuthibitishwa na kupata kitu kamili. Utengano huo sio dosari; ni kile ambacho chombo kimeundwa kwa ajili yake: superRefine ni mahali ambapo mantiki ya sehemu-msingi huenda wakati haiwezi kuonyeshwa katika muundo wa schema yenyewe. Kinachojulikana pia hapa ni kile ambacho schema hii haionyeshi. Haina dhana ya kurasa, hakuna dhana ya ni nyanja gani zinaonekana kwa wakati gani, na hakuna dhana ya urambazaji. Yote hayo yataishi mahali pengine. Sehemu ya Fomu
leta {useForm, useWatch } kutoka "react-hook-form";leta {zodResolver } kutoka "@hookform/resolvers/zod"; leta {useMutation } kutoka "@tanstack/react-query"; leta {useState, useMemo } kutoka "react"; leta {formSchema} kutoka kwa "Daschema";
const STEPS = ["maelezo", "agiza", "akaunti", "hakiki"];
chapa OrderPayload = FormData & { subtotal: number; ushuru: nambari; jumla: nambari };
kazi ya kuuza nje RHFMultiStepForm() { const [hatua, setStep] = useState(0);
const mutation = useMutation ({ mutationFn: async (mzigo wa malipo: OrderPayload) => { const res = subiri kuchota("/api/orders", { njia: "POST", vichwa: { "Content-Type": "application/json" }, mwili: JSON.stringify(payload), }); ikiwa (!res.ok) kutupa Hitilafu mpya("Imeshindwa kuwasilisha"); rudisha res.json(); }, });
const { register, control, handleSubmit, formState: { errors }, } = useForm
rudisha (
);}Tazama Pen SurveyJS-03-RHF [iliyogawanyika] kwa kutoweka kwa sita. Kuna mengi yanatokea hapa, na inafaa kupunguza kasi ili kugundua ni wapi mambo yaliishia.
Thamani zinazotokana - jumla ndogo, kodi, jumla - zinakokotwa katika kijenzi kupitia useWatch na useMemo kwa sababu zinategemea thamani za sehemu za moja kwa moja na hakuna mahali pengine pa asili pa kuzipata. Sheria za mwonekano wa jina la mtumiaji, nenosiri, maoni chanya, na uboreshajiMaoni yanaishi katika JSX kama masharti ya ndani. Mantiki ya kuruka hatua - ukurasa wa mapitio unaonekana tu wakati jumla >= 100 - umepachikwa kwenye onyesho la kutofautisha Wasilisha na sharti la utekelezaji kwenye hatua ya 3. Urambazaji wenyewe ni kihesabu cha useState ambacho tunaongeza sisi wenyewe. React Query hushughulikia majaribio tena, akiba na kubatilisha. Fomu huita tu mutation.mutate na data iliyothibitishwa.
Hakuna kati ya haya ambayo ni makosa, per se. Hii bado ni idiomatic React, na kijenzi kina utendaji mzuri kutokana na jinsi RHF inavyotenga re-render. Lakini ikiwa ungekabidhi hii kwa mtu ambaye hakuwa ameiandika na kumwomba aeleze ni chini ya hali gani ukurasa wa ukaguzi unaonekana, wangelazimika kufuatilia kupitia kwa OnyeshoTuma, hatua ya 3 ya kutoa masharti, na mantiki ya kitufe cha nav - sehemu tatu tofauti - ili kuunda upya sheria ambayo inaweza kuwa imeelezwa katika mstari mmoja. Fomu inafanya kazi, ndio, lakini tabia hiyo haiwezi kukaguliwa kama mfumo. Inapaswa kutekelezwa kiakili. Muhimu zaidi, kuibadilisha kunahitaji ushiriki wa uhandisi. Hata mabadiliko madogo, kama vile kurekebisha hatua ya ukaguzi inapoonekana, inamaanisha kuhariri kijenzi, kusasisha uthibitishaji, kufungua ombi la kuvuta, kusubiri kukaguliwa, na kupeleka tena. Sehemu ya 2: Inaendeshwa na Schema (SurveyJS) Sasa hebu tujenge mtiririko sawa kwa kutumia schema. Ufungaji npm sakinisha survey-core survey-react-ui @tanstack/react-query
survey-coreInjini ya wakati wa kukimbia yenye leseni ya MIT inayotumia uwasilishaji wa fomu ya SurveyJS - sehemu tunayojali hapa. Inachukua utaratibu wa JSON, huunda muundo wa ndani kutoka kwayo, na kushughulikia kila kitu ambacho kingeishi katika kipengele chako cha React: kutathmini vielezi vya mwonekano, kuweka thamani zinazotokana na kompyuta, kudhibiti hali ya ukurasa, kufuatilia uthibitishaji, na kuamua ni nini "kamili" inamaanisha kutokana na kurasa ambazo zilionyeshwa.
survey-react-uiThe UI / safu ya uwasilishaji inayounganisha muundo huo na React. Kimsingi ni kipengele cha
Kwa pamoja, wanakupa muda wa kutekeleza kikamilifu, wa kurasa nyingi bila kuandika safu moja ya mtiririko wa udhibiti. Umbizo la schema yenyewe, kama ilivyosemwa hapo awali, ni JSON tu - hakuna DSL au wamiliki wowote. Unaweza kuiweka ndani, kuiingiza kutoka kwa faili, kuileta kutoka kwa API, au kuihifadhi kwenye safu ya hifadhidata na kuitia maji wakati wa utekelezaji. Fomu Sawa, Kama Data Hapa kuna fomu sawa, wakati huu inaonyeshwa kama kitu cha JSON. Ratiba inafafanua kila kitu: muundo, uthibitishaji, sheria za mwonekano, hesabu zinazotokana, usogezaji wa ukurasa - na kuikabidhi kwa Muundo unaoitathmini wakati wa utekelezaji. Hivi ndivyo inavyoonekana kwa ukamilifu:
export const surveySchema = { title: "Order Flow", showProgressBar: "juu", kurasa: [ {jina: "maelezo", vipengele: [ {aina: "maandishi", jina: "firstName", isRequired: true }, { type: "text", name: "email", inputType: "email", isRequired: true, validator: [{ barua pepe ya maandishi}] "Katika barua pepe": [{ aina ya barua pepe:] }, {jina: "agizo", vipengele: [ {aina: "maandishi", jina: "bei", pembejeoType: "nambari", Thamani chaguo-msingi: 0 }, {aina: "maandishi", jina: "wingi", inputType: "namba", Thamani chaguo-msingi: 1 }, {aina: "kunjuzi",jina: "TaxRate", Thamani chaguo-msingi: 0.1, chaguo: [ {thamani: 0.05, maandishi: "5%" }, {thamani: 0.1, maandishi: "10%" }, {thamani: 0.15, maandishi: "15%" } ] }, { type: "expression", jina: "{subtotal type}"}: usemi: {quantity} "expression", name: "tax", usemi: "{subtotal} {taxRate}" }, { type: "expression", name: "jumla", usemi: "{subtotal} + {tax}" } ] }, {jina: "akaunti", vipengele: [ {aina: "radiogroup", jina: "hasAccount", chaguzi: [""]"ndiyo jina", {Hapana, maandishi} inayoonekanaKama: "{hasAccount} = 'Ndiyo'", Inahitajika: kweli }, {aina: "maandishi", jina: "nenosiri", inputType: "nenosiri", inayoonekanaKama: "{hasAccount} = 'Ndiyo'", Inahitajika: kweli, vithibitishaji: [{ type: "text", minLength: 6, text: "Min: "Min : "} ratings: "Min :}} ratings "satisfaction", rateMin: 1, rateMax: 5 }, { type: "comment", name: "positiveFeedback", inayoonekanaKama: "{satisfaction} >= 4" }, { type: "comment", name: "improvementFeedback", inayoonekanaIf: "{satisfaction} <= 2" } :] :0 view{}, Kama inaonekana, {} : = 1, {} tazama, {} ] vipengele: [] } ]};
Linganisha hii na toleo la RHF kwa muda.
Kizuizi cha superRefine ambacho kinahitaji jina la mtumiaji na nenosiri kimetoweka. InaonekanaKama: "{hasAccount} = 'Ndiyo'" pamoja na isRequired: true hushughulikia masuala yote mawili kwa pamoja, kwenye sehemu yenyewe, ambapo ungetarajia kuyapata. Msururu wa useWatch + useMemo ambao ulikokotoa jumla ndogo, kodi na jumla unabadilishwa na sehemu tatu za usemi zinazorejeleana kwa majina. Hali ya ukurasa wa ukaguzi, ambayo katika toleo la RHF iliweza kujengwa upya kwa kufuatilia tu kupitia showSubmit, hatua ya 3 kutoa tawi. Na mwishowe, mantiki ya kitufe cha nav ni kitu kimoja kinachoonekanaKama kwenye kitu cha ukurasa.
Mantiki hiyo hiyo ipo. Ni kwamba tu schema inaipa mahali pa kuishi ambapo inaonekana kwa kutengwa, badala ya kuenea katika sehemu. Pia, kumbuka kuwa schema hutumia aina: 'maneno' kwa jumla ndogo, kodi, na jumla. Usemi ni wa kusoma tu na hutumiwa hasa kuonyesha thamani zilizokokotwa. SurveyJS pia inasaidia aina: 'html' kwa maudhui tuli, lakini kwa thamani zilizokokotwa, usemi ndio chaguo sahihi. Sasa kwa upande wa React. Utoaji na Uwasilishaji Rahisi sana. Waya onComplete kwa API yako kwa njia ile ile - kupitia useMutation au kuleta rahisi:
agiza {useState, useEffect, useRef } kutoka "react"; import {useMutation } kutoka "@tanstack/react-query"; leta { Model } kutoka "survey-core"; import { Survey } kutoka "survey-react-ui"; import "survey-core/survey-cores".css.
kazi ya kuuza nje SurveyForm() { const [model] = useState(() => Model mpya(surveySchema));
const mutation = useMutation ({ mutationFn: async (data) => { const res = subiri kuchota("/api/orders", { njia: "POST", vichwa: { "Content-Type": "application/json" }, mwili: JSON.stringify(data), }); ikiwa (!res.ok) kutupa Hitilafu mpya("Imeshindwa kuwasilisha"); rudisha res.json(); }, });
const mutationRef = useRef(mutation); mutationRef.current = mutation; useEffect(() => { const handler = (mtumaji) => mutationRef.current.mutate(sender.data); model.onComplete.add(handler); rudisha () => model.onComplete.remove( handler); }, [model]); // ref huepuka kusajili tena kidhibiti kila toleo (mabadiliko ya kitambulisho cha kitu)
kurudi (
<>
Tazama Pen SurveyJS-03-SurveyJS [iliyogawanyika] kwa kutoweka kwa sita.
onComplete moto mtumiaji anapofika mwisho wa ukurasa wa mwisho unaoonekana. Kwa hivyo ikiwa jumla haivuka 100 na ukurasa wa ukaguzi kurukwa, bado huwaka ipasavyo kwa sababu SurveyJS hutathmini mwonekano kabla ya kuamua "ukurasa wa mwisho" inamaanisha nini. Kisha, data ya mtumaji huwa na majibu yote pamoja na thamani zilizokokotwa (jumla ndogo, kodi, jumla) kama sehemu za daraja la kwanza, kwa hivyo upakiaji wa API ni sawa na toleo la RHF lilikusanywa mwenyewe kwenye onSubmit. Themuundo wa mutationRef ni ule ule ambao ungefikia mahali popote unapohitaji kidhibiti cha tukio thabiti juu ya thamani inayobadilika kwa kila toleo - hakuna SurveyJS mahususi kuihusu.
Sehemu ya React haina tena mantiki ya biashara hata kidogo. Hakuna useWatch, hakuna JSX ya masharti, hakuna kihesabu hatua, hakuna msururu wa useMemo, hakuna SuperRefine. React ni kufanya kile ambacho ni kizuri sana: kutoa kijenzi na kukiunganisha kwa simu ya API. Ni Nini Kilichotoka Kwenye React?
Wasiwasi Mkusanyiko wa RHF UtafitiJS Mwonekano matawi ya JSX inayoonekanaKama Maadili yanayotokana useWatch / useMemo kujieleza Sheria za uwanja mtambuka Safisha zaidi Masharti ya schema Urambazaji hali ya hatua Ukurasa unaoonekanaKama Mahali pa utawala Imesambazwa katika faili zote Imewekwa katikati katika schema
Kinachosalia katika React ni mpangilio, mitindo, nyaya za uwasilishaji, na ujumuishaji wa programu, ambayo ni kusema, vitu vya React vimeundwa kwa ajili ya kweli. Kila kitu kingine kilihamishwa kwenye schema, na kwa sababu schema ni kitu cha JSON tu, inaweza kuhifadhiwa kwenye hifadhidata, iliyotolewa bila msimbo wako wa maombi, au kuhaririwa kupitia zana za ndani bila kuhitaji kupelekwa. Msimamizi wa bidhaa ambaye anahitaji kubadilisha kiwango cha juu kinachoanzisha ukurasa wa ukaguzi anaweza kufanya hivyo bila kugusa kijenzi. Hiyo ni tofauti ya maana ya kiutendaji kwa timu ambapo tabia ya umbo hubadilika mara kwa mara na haichochewi na wahandisi kila wakati. Wakati wa Kutumia Kila Mbinu? Hapa kuna sheria nzuri ambayo inanifanyia kazi: fikiria kufuta fomu kabisa. Ungepoteza nini?
Ikiwa ni skrini, unataka fomu zinazoendeshwa na vipengele. Ikiwa ni mantiki ya biashara, kama vile vizingiti, sheria za matawi, na mahitaji ya masharti ambayo yanajumuisha maamuzi halisi, ungependa injini ya schema.
Vile vile, ikiwa mabadiliko yanayokuja kwako yanahusu lebo, sehemu, na mpangilio, RHF itakuhudumia vyema. Iwapo zinahusu masharti, matokeo na sheria ambazo wasimamizi wako au timu ya wanasheria wanaweza kuhitaji kurekebisha Jumanne alasiri bila kuandikisha tikiti, kielelezo cha taratibu kilicho na SurveyJS ndicho kinachofaa zaidi. Mbinu hizi mbili si kweli katika ushindani na kila mmoja. Wanashughulikia aina tofauti za matatizo, na kosa linalostahili kuepukwa ni kulinganisha ufupisho na uzito wa mantiki - kutibu mfumo wa sheria kama kipengele kwa sababu hiyo ndiyo zana inayojulikana, au kufikia injini ya sera kwa sababu fomu ilikua hatua tatu na kupata uga wa masharti. Fomu tuliyounda hapa inakaa karibu na mpaka kwa makusudi, changamano vya kutosha kufichua tofauti lakini sio kali sana hivi kwamba ulinganisho unahisi kuwa umeibiwa. Aina nyingi za kweli ambazo zimepata shida katika codebase yako labda hukaa karibu na mpaka huo huo, na swali kawaida ni ikiwa kuna mtu yeyote ametaja kile walicho. Tumia React Hook Form + Zod wakati:
Fomu zina mwelekeo wa CRUD; Mantiki ni duni na inaendeshwa na UI; Wahandisi wanamiliki tabia zote; Backend inabaki kuwa chanzo cha ukweli.
Tumia SurveyJS wakati:
Fomu husimba maamuzi ya biashara; Sheria hubadilika bila kutumia UI; Mantiki lazima ionekane, iweze kukaguliwa, au itolewe toleo; Wasio wahandisi huathiri tabia; Fomu sawa lazima iendeshwe kwenye sehemu nyingi za mbele.