Artikulu hau SurveyJS-ek babestutakoa da React-eko garatzaile gehienek partekatzen duten eredu mental bat dago inoiz ozen eztabaidatu gabe. Formak beti osagai izan behar direla. Honek honelako pila bat esan nahi du:
React Hook formularioa tokiko estaturako (errendaketa minimoak, eremu ergonomikoa erregistratzea, interakzio ezinbestekoa). Zod baliozkotzeko (sarreraren zuzentasuna, muga-balioztapena, mota seguruaren analisia). React Query backend-erako: bidalketa, berriro saiakerak, cachean gordetzea, zerbitzariaren sinkronizazioa eta abar.
Eta inprimaki gehienentzat - zure saio-hasierako pantailak, zure ezarpen-orriak, zure CRUD modalitateak - oso ondo funtzionatzen du. Pieza bakoitzak bere lana egiten du, garbi konposatzen dute, eta zure produktua benetan bereizten duten aplikazioaren ataletara pasa dezakezu. Baina noizean behin, inprimaki bat lehenagoko erantzunen araberako ikusgarritasun-arauak edo hiru eremutan zehar jauzi egiten diren balio eratorriak bezalako gauzak pilatzen hasten dira. Baliteke orri osoak ere saltatu edo erakutsi beharko liratekeen guztirako batean oinarrituta. UseWatch eta inline adar batekin kudeatzen duzu lehen baldintza, eta hori ondo dago. Gero beste bat. Orduan superRefine-ra iristen ari zara zure Zod eskemak modu normalean adierazi ezin dituen eremuen arteko arauak kodetzeko. Ondoren, urratsen nabigazioa negozio-logika isurtzen hasten da. Noizbait, eraiki duzunari begiratzen diozu eta konturatzen zara inprimakia jada ez dela benetan UI. Erabaki prozesu bat baino gehiago da, eta osagaien zuhaitza gorde zenuen tokian dago. Hemen uste dut React-en formen eredu mentala apurtzen dela, eta benetan ez da inoren errua. RHF + Zod pila bikaina da diseinatu zenerako. Kontua da erabiltzen jarraitu ohi dugula bere abstrakzioak arazoarekin bat datozen puntutik igarota, alternatibak formei buruz guztiz pentsatzeko beste modu bat eskatzen duelako. Artikulu hau alternatiba horri buruzkoa da. Hau erakusteko, urrats anitzeko inprimaki bera eraikiko dugu bi aldiz:
React Hook formularioa + Zod-ekin bidaltzeko React Query-ra kabletuta, SurveyJS-rekin, inprimaki bat datu gisa tratatzen du —JSON eskema soil bat— osagaien zuhaitz bat baino.
Baldintza berdinak, baldintzazko logika bera, amaieran API dei bera. Ondoren, zer mugitu den eta zer geratu den mapatuko dugu, eta zein eredu erabili behar duzun eta noiz erabakitzeko modu praktiko bat ezarriko dugu. Eraikitzen ari garen formularioa:
Inprimaki honek 4 urratseko fluxua erabiliko du: 1. urratsa: Xehetasunak
Izena (beharrezkoa), Posta elektronikoa (beharrezkoa, baliozko formatua).
2. urratsa: ordena
Unitatearen prezioa, Kantitatea, Zerga tasa, Eratorria: Azpi-totala, Zerga, Guztira.
3. urratsa: kontua eta iritzia
Ba al duzu konturik? (Bai/Ez) Bai bada → erabiltzaile izena + pasahitza, biak beharrezkoak. Ez bada → 1. urratsean dagoeneko bildutako mezu elektronikoa.
Asebetetze balorazioa (1-5) ≥ 4 bada → galdetu "Zer gustatu zaizu?" ≤ 2 bada → galdetu "Zer hobetu dezakegu?"
4. urratsa: berrikuspena
Guztira >= 100 bada bakarrik agertzen da Azken bidalketa.
Hau ez da muturrekoa. Baina nahikoa da ezberdintasun arkitektonikoak agerian uztea. 1. zatia: osagaiek gidatutakoa (erreakzionatzeko amua + zod) Instalazioa npm instalatu react-hook-form zod @hookform/resolvers @tanstack/react-query
Zod eskema Has gaitezen Zod eskemarekin, normalean hor finkatzen baita formaren forma. Lehenengo bi urratsetarako — xehetasun pertsonalak eta eskaeraren sarrerak — dena erraza da: beharrezko kateak, gutxieneko zenbakiak eta enumerazioa. Zati interesgarria baldintzapeko arauak adierazten saiatzen zarenean hasten da.
inportatu {z } "zod"-tik;
export const formSchema = z.object({ firstName: z.string().min(1, "Derrigorrezkoa"), posta elektronikoa: z.string().email("E-posta baliogabea"), prezioa: z.number().min(0), kantitatea: z.number().min(1), taxRate: z.number(), hasAccount(No"]), hasAccount: "Y:" z.string().optional(), pasahitza: z.string().optional(), gogobetetasuna: z.number().min(1).max(5), positiveFeedback: z.string().optional(), improvementFeedback: z.string().optional(),}).superRefine((datuak, ctx) => { if (datuak) === "Yes Account. ctx.addIssue({ kodea: "pertsonalizatua", bidea: ["erabiltzaile-izena"], mezua: "Derrigorrezkoa" }); } if (!data.password || data.password.length < 6) { ctx.addIssue({ kodea: "personalizatu", bidea: ["pasahitza"], mezua: "Gutxienez 6 karaktere}"});
if (data.satisfaction >= 4 && !data.positiveFeedback) { ctx.addIssue ({ kodea: "personalizatu", bidea: ["positiveFeedback"], mezua: "Mesedez, partekatu gustatu zaizuna" }); }
bada (data.satisfaction <= 2 && !data.improvementFeedback) { ctx.addIssue ({ kodea: "pertsonalizatua", bidea:["improvementFeedback"], mezua: "Mesedez, esaiguzu zer hobetu behar dugun"}); }});
esportatu mota FormData = z.infer
Kontuan izan erabiltzaile-izena eta pasahitza aukerako() gisa idazten direla, nahiz eta baldintzapean beharrezkoak diren, Zod-en mota-mailako eskemak objektuaren forma deskribatzen duelako, ez eremuek garrantzia dutenean arautzen duten arauak. Baldintza-eskakizunak superRefine barruan bizi behar du, forma balioztatu ondoren exekutatzen dena eta objektu osorako sarbidea duen. Banaketa hori ez da akats bat; tresna hori zertarako diseinatuta dago: superRefine eremuen arteko logika nora doa eskema-egituran bertan adierazi ezin denean. Hemen ere nabarmentzen dena eskema honek adierazten ez duena da. Ez du orrialdeen kontzepturik, ez dago zein eremutan ikusgai dagoen kontzepturik eta ez du nabigazio kontzepturik. Hori guztia beste nonbait biziko da. Inprimakiaren osagaia
inportatu { useForm, useWatch } "react-hook-form"-tik; inportatu { zodResolver } "@hookform/resolvers/zod"-tik; inportatu { useMutation } "@tanstack/react-query"-tik; inportatu { useState, useMemo } "react"-tik; inportatu { formSchema, "FormDataschema" motatik;
const STEPS = ["xehetasunak", "eskatu", "kontua", "berrikuspena"];
idatzi OrderPayload = FormData & { azpitotala: zenbakia; zerga: zenbakia; guztira: zenbakia };
esportatu funtzioa RHFMultiStepForm () { const [step, setStep] = useState (0);
const mutation = erabiliMutazioa({ mutationFn: async (karga: OrderPayload) => { const res = itxaron eskura ("/api/aginduak", { metodoa: "POST", goiburuak: { "Content-Type": "application/json" }, gorputza: JSON.stringify (karga erabilgarria), }); if (!res.ok) throw new Error("Huts egin du bidaltzean"); itzuli res.json(); }, });
const { register, control, handleSubmit, formState: { errors }, } = useForm
itzuli (
);}Ikusi Pen SurveyJS-03-RHF [forked] sixthextinction-ek. Hemen dezente gertatzen da, eta merezi du moteltzea gauzak non amaitu diren ohartzeko.
Eratorritako balioak (subtotala, zerga, guztira) osagaian kalkulatzen dira useWatch eta useMemo bidez, eremu biziko balioen araberakoak direlako eta ez dagoelako beste leku naturalik. Erabiltzaile-izena, pasahitza, positiveFeedback eta hobekuntzaFeedback-en ikusgarritasun-arauak JSX-n zuzentzen dira lineako baldintza gisa. Urrats-saltatzeko logika - berrikuspen orria guztira >= 100 denean bakarrik agertzen da - showSubmit aldagaian eta errendatze-baldintza 3. urratsean txertatuta dago. Nabigazioa bera eskuz gehitzen ari garen useState kontagailua besterik ez da. React Query-k birsaioak, cachean gordetzea eta baliogabetzea kudeatzen ditu. Inprimakiak mutation.mutate deitzen du baliozko datuekin.
Hauetako ezer ez dago gaizki, berez. Hau React idiomatikoa da oraindik, eta osagaia nahiko eraginkorra da RHF-k berriro errendatzeak isolatzen dituenari esker. Baina hau idatzi ez zuen norbaiti eman eta berrikuspen orria zein baldintzatan agertzen den azaltzeko eskatuko badiozu, showSubmit-en, 3. urratseko errendatze-baldintzaren eta nabigazio-botoiaren logika - hiru leku bereizi - lerro batean adierazi zitekeen arau bat berreraikitzeko egin beharko luke. Formak funtzionatzen du, bai, baina portaera ez da benetan ikuskagarria sistema gisa. Buruz exekutatu behar da. Are garrantzitsuagoa dena, hura aldatzeak ingeniaritzaren parte hartzea eskatzen du. Nahiz eta doikuntza txiki bat, berrikuspen urratsa agertzen denean doitzea, osagaia editatzea, baliozkotzea eguneratzea, tira-eskaera bat irekitzea, berrikuspenaren zain egotea eta berriro zabaltzea esan nahi du. 2. zatia: eskemak bultzatuta (SurveyJS) Orain eraiki dezagun fluxu bera eskema bat erabiliz. Instalazioa npm instalatu survey-core survey-react-ui @tanstack/react-query
survey-core SurveyJS-en inprimakiak errendatzea ahalbidetzen duen MIT lizentziadun plataformatik independentea den exekuzio-motorra - hemen axola zaigun zatia. JSON eskema bat hartzen du, bertatik barne-eredu bat eraikitzen du eta bestela zure React osagaian biziko litzatekeen guztia maneiatzen du: ikusgarritasun-adierazpenak ebaluatzea, eratorritako balioak kalkulatzea, orriaren egoera kudeatzea, baliozkotzea jarraipena egitea eta "osoa" zer esan nahi duen erabakitzea, benetan erakutsi diren orrialdeak kontuan hartuta.
survey-react-ui Eredu hori React-ekin lotzen duen UI / errendatze geruza. Funtsean,
Elkarrekin, orri anitzeko inprimakien exekuzio-denbora guztiz funtzionala ematen dizute kontrol-fluxu-lerro bakar bat idatzi gabe. Eskema formatua bera, lehen esan bezala, JSON bat besterik ez da, ez DSLrik edo jabedun ezer. Sartu, fitxategi batetik inportatu, API batetik eskuratu edo datu-baseko zutabe batean gorde eta exekuzioan hidratatu dezakezu. Forma Bera, Datu gisa Hona hemen forma bera, oraingoan JSON objektu gisa adierazita. Eskemak dena definitzen du: egitura, baliozkotzea, ikusgarritasun-arauak, kalkulu eratorriak, orriaren nabigazioa, eta exekuzioan ebaluatzen duen Eredu bati ematen dio. Hona hemen nolakoa den osorik:
export const surveySchema = { title: "Order Flow", showProgressBar: "top", orriak: [ { name: "details", elements: [ { type: "text", name: "firstName", isRequired: true }, { type: "text", name: "email", inputType: "email", isRequired: true, validtors: [} "type: in the email"] izena: "ordena", elementuak: [ { mota: "testua", izena: "prezioa", inputType: "zenbakia", defaultValue: 0}, { type: "testua", izena: "kantitatea", inputType: "zenbakia", defaultValue: 1}, { type: "dropdown",izena: "taxRate", balio lehenetsia: 0.1, aukerak: [ { balioa: 0.05, testua: "% 5" }, { balioa: 0.1, testua: "% 10" }, { balioa: 0.15, testua: "% 15" } ] }, { mota: "adierazpena", izena: "azpitotala",} adierazpena, {: "kantitatea}" "prezio"} adierazpena, {: "kantitatea}""} adierazpena: "zerga", adierazpena: "{subtotal} {taxRate}" }, { mota: "adierazpena", izena: "guztira", esamoldea: "{azpitotala} + {zerga}" } ] }, { izena: "kontua", elementuak: [ { mota: "irratitaldea", izena: "hasAccount", aukerak: ["Bai", "Ez"] }, izena, {: "guk izena" }, izena ikusgai "{hasAccount} = 'Bai'", isRequired: true }, { type: "text", name: "password", inputType: "password", visibleIf: "{hasAccount} = 'Yes'", isRequired: true, baliozkotzaileak: [{ type: "text", minLength: 6, text: "Gutxieneko 6 karaktere}," {}", "factions" izenak rateMin: 1, rateMax: 5 }, { type: "comment", name: "positiveFeedback", visibleIf: "{satisfaction} >= 4" }, { type: "comment", name: "improvementFeedback", visibleIf: "{satisfaction} <= 2" } ] }, {}: >: "review" elementuak, {}: >: "re view", {: I = 0 elementu ikusgai [] } ]};
Konparatu hau RHF bertsioarekin une batez.
Baldintzapean eskatzen zituen erabiltzaile-izena eta pasahitza zuen superRefine blokea desagertu egin da. visibleIf: "{hasAccount} = 'Bai'" isRequired-ekin konbinatuta: true-k bi kezkak batera kudeatzen ditu, eremuan bertan, aurkitzea espero zenituzkeen tokian. Azpitotalak, zergak eta guztira kalkulatu zituen useWatch + useMemo katea elkarri izenaz erreferentzia egiten dioten hiru adierazpen-eremurekin ordezkatzen da. Berrikuspen-orriaren baldintza, RHF bertsioan berreraiki daitekeena showSubmit bidez, 3. urratsa errendatzeko adarraren bidez bakarrik jarraituz. Eta azkenik, nav botoiaren logika ikusgaiIf propietate bakarra da orrialdeko objektuan.
Logika bera dago. Besterik da eskemak isolatuta ikusten den bizitzeko tokia ematen diola, osagaian zehar zabaldu beharrean. Gainera, kontuan izan eskemak mota erabiltzen duela: 'adierazpena' azpitotalerako, zergarako eta guztirarako. Adierazpena irakurtzeko soilik da eta kalkulatutako balioak bistaratzeko erabiltzen da batez ere. SurveyJS-k mota ere onartzen du: 'html' eduki estatikorako, baina kalkulatutako balioetarako, adierazpena aukera egokia da. Orain Erreakzionaren alde. Errendatzea Eta Bidalketa Oso sinplea. Konektatu onComplete zure APIra modu berean — useMutation edo eskuratze arruntaren bidez:
inportatu { useState, useEffect, useRef } "react"-tik;inportatu { useMutation } "@tanstack/react-query"-tik;inportatu { Model } "survey-core"-tik;inportatu { Survey } "survey-react-ui"tik; inportatu "survey-core/survey-core.css";
esportatu funtzioa SurveyForm () { const [model] = useState (() => new Model (surveySchema));
const mutation = erabiliMutazioa({ mutationFn: async (datuak) => { const res = itxaron eskura ("/api/aginduak", { metodoa: "POST", goiburuak: { "Content-Type": "application/json" }, gorputza: JSON.stringify(datuak), }); if (!res.ok) throw new Error("Huts egin du bidaltzean"); itzuli res.json(); }, });
const mutationRef = useRef (mutazioa); mutationRef.current = mutazioa; useEffect(() => { const handler = (igorlea) => mutationRef.current.mutate (sender.data); model.onComplete.add (kudeatzailea); return () => model.onComplete.remove (kudeatzailea); }, [model]); // Refk kudeatzailea berriro erregistratzea saihesten du errendatze bakoitzean (mutazio objektuaren identitatea aldatzen da)
itzuli (
<>
Ikusi Pen SurveyJS-03-SurveyJS [forked] sixthextinction-ek.
onComplete-k erabiltzailea ikusgai dagoen azken orrialdearen amaierara iristen denean abiarazten da. Beraz, guztira inoiz ez bada 100 gainditzen eta berrikuspen orria saltatzen bada, behar bezala piztuko da SurveyJS-k ikusgarritasuna ebaluatzen duelako "azken orria" zer esan nahi duen erabaki aurretik. Ondoren, sender.data-k erantzun guztiak ditu kalkulatutako balioekin batera (azpitotala, zerga, guztira) lehen mailako eremu gisa, beraz, API karga karga RHF bertsioak onSubmit-en eskuz muntatutakoaren berdina da. ThemutationRef eredua errendatze bakoitzean aldatzen den balio baten gainean gertaeren kudeatzaile egonkor bat behar duzun edozein tokitara iritsiko zenituzkeen berdina da - ezer SurveyJS-ri buruz zehatzik.
React osagaiak jada ez du negozio-logikarik. Ez dago useWatch, ez baldintzazko JSX, ez urrats kontagailurik, ez useMemo katerik, ez superRefinerik. React benetan ona dena egiten ari da: osagai bat errendatzea eta API dei batera kableatzea. Zer mugitu zen erreakziotik?
Kezka RHF pila InkestaJS Ikusgarritasuna JSX adarrak ikusgaiBada Balio eratorriak erabiliIkusi / erabiliOharra adierazpena Zelaien arteko arauak superFindu Eskemaren baldintzak Nabigazioa urrats-egoera Orria ikusgaiIf Arauaren kokapena Fitxategietan banatuta Eskeman zentralizatua
React-en geratzen dena diseinua, estiloa, bidalketa kableatzea eta aplikazioen integrazioa da, hau da, React benetan diseinatuta dagoen gauzak. Beste guztia eskeman mugitu zen, eta eskema JSON objektu bat besterik ez denez, datu-base batean gorde daiteke, zure aplikazioaren kodearen arabera bertsionatu edo barne-tresnen bidez editatu daiteke inplementatu beharrik gabe. Berrikuspen orria abiarazten duen atalasea aldatu behar duen produktu-kudeatzaileak hori egin dezake osagaia ukitu gabe. Hori desberdintasun operatibo esanguratsua da inprimakiaren portaera maiz eboluzionatzen duten taldeentzat, eta ez dute beti ingeniariek gidatzen. Noiz erabili planteamendu bakoitza? Hona hemen niretzat balio duen arau on bat: imajina ezazu inprimakia guztiz ezabatzen duzula. Zer galduko zenuke?
Pantailak badira, osagaiek gidatutako inprimakiak nahi dituzu. Negozio-logika bada, benetako erabakiak kodetzen dituzten atalaseak, adarkatze-arauak eta baldintza-eskakizunak bezalakoak, eskema-motorra nahi duzu.
Era berean, datozen aldaketak etiketa, eremu eta diseinuari buruzkoak badira gehienbat, RHFk ondo balioko dizu. Baldintza, emaitzei eta arauei buruzkoak badira, zure operazioek edo talde juridikoek astearte arratsaldean txartel bat aurkeztu gabe egokitu beharko lituzketen arauak, SurveyJS-ren eskema-eredua zintzoagoa da. Bi ikuspegi hauek ez daude benetan elkarren lehian. Arazo-klase desberdinak jorratzen dituzte, eta saihestu beharreko akatsa abstrakzioa logikaren pisuarekin bat ez etortzea da: arau-sistema bat osagai gisa tratatzea tresna ezaguna delako, edo politika-motorra iristea, inprimaki bat hiru urratsetara hazi eta baldintzapeko eremu bat eskuratu zuelako. Hemen eraiki dugun forma mugatik gertu dago nahita, aldea agerian uzteko nahikoa konplexua, baina ez da hain muturrekoa konparazioa txundituta sentitzen den. Zure kode-oinarrian zail bihurtu diren forma erreal gehienak muga beraren ondoan egoten dira ziurrenik, eta galdera izan ohi da norbaitek benetan zer diren izendatu duen ala ez. Erabili React Hook Form + Zod noiz:
Formak CRUDera bideratzen dira; Logika azalekoa eta UI-k gidatua da; Ingeniariek portaera guztien jabe dira; Backendek egiaren iturria izaten jarraitzen du.
Erabili SurveyJS noiz:
Inprimakiek negozio-erabakiak kodetzen dituzte; Arauak UI-tik independenteki eboluzionatzen dira; Logikak ikusgai, ikuskagarria edo bertsionatua izan behar du; Ingeniariak ez direnek portaeran eragiten dute; Inprimaki bera frontend askotan exekutatu behar da.