Kini nga artikulo gi-sponsor sa SurveyJS Adunay usa ka modelo sa pangisip nga gipaambit sa kadaghanan sa mga developer sa React nga wala gyud kini hisgutan nga kusog. Kana nga mga porma kanunay nga kinahanglan nga mga sangkap. Kini nagpasabut nga usa ka stack sama sa:
React Hook Form para sa lokal nga estado (minimal nga re-render, ergonomic field registration, imperative interaction). Zod para sa validation (input correctness, boundary validation, type-safe parsing). React Query para sa backend: pagsumite, pagsulay pag-usab, pag-cache, pag-sync sa server, ug uban pa.
Ug alang sa kadaghanan sa mga porma - ang imong mga screen sa pag-login, ang imong mga panid sa setting, ang imong mga modal sa CRUD - kini molihok nga maayo. Ang matag piraso nagbuhat sa iyang trabaho, limpyo ang paghimo niini, ug mahimo ka nga magpadayon sa mga bahin sa imong aplikasyon nga tinuud nga nagpalahi sa imong produkto. Apan matag karon ug unya, ang usa ka porma magsugod sa pagtigum sa mga butang sama sa visibility nga mga lagda nga nagdepende sa naunang mga tubag, o nakuha nga mga bili nga mosaka sa tulo ka field. Tingali bisan ang tibuuk nga mga panid nga kinahanglan laktawan o ipakita base sa usa ka total nga nagdagan. Gidumala nimo ang una nga kondisyon nga adunay usa ka useWatch ug usa ka inline nga sanga, nga maayo. Unya lain. Unya nakab-ot nimo ang superRefine aron ma-encode ang mga lagda sa cross-field nga dili mapahayag sa imong Zod schema sa normal nga paagi. Pagkahuman, ang lakang sa pag-navigate nagsugod sa pagtulo sa lohika sa negosyo. Sa usa ka punto, imong gitan-aw kung unsa ang imong gitukod ug nahibal-an nga ang porma dili na UI. Kini labaw pa sa usa ka proseso sa pagdesisyon, ug ang punoan sa sangkap mao ra kung diin nimo kini gitipigan. Dinhi sa akong hunahuna ang modelo sa pangisip alang sa mga porma sa React naguba, ug wala gyud kini sayup. Ang RHF + Zod stack maayo kaayo sa kung unsa kini gidisenyo. Ang isyu mao nga kita adunay kanunay nga paggamit niini lapas sa punto diin ang mga abstraction niini mohaum sa problema tungod kay ang alternatibo nanginahanglan usa ka lahi nga paagi sa paghunahuna bahin sa mga porma sa hingpit. Kini nga artikulo bahin sa kana nga alternatibo. Aron ipakita kini, magtukod kami sa eksaktong parehas nga multi-step nga porma sa makaduha:
Uban sa React Hook Form + Zod wired sa React Query para sa pagsumite, Uban sa SurveyJS, nga nagtagad sa usa ka porma ingon data - usa ka yano nga JSON schema - kaysa usa ka sangkap nga punoan.
Parehas nga kinahanglanon, parehas nga conditional logic, parehas nga tawag sa API sa katapusan. Dayon among i-mapa ang eksakto kung unsa ang mibalhin ug unsa ang nagpabilin, ug ibutang ang praktikal nga paagi sa pagdesisyon kung unsang modelo ang imong gamiton, ug kanus-a. Ang porma nga among gitukod:
Kini nga porma mogamit ug 4 ka lakang nga dagan: Lakang 1: Mga Detalye
Unang ngalan (gikinahanglan), Email (gikinahanglan, balido nga pormat).
Lakang 2: Pag-order
Presyo sa yunit, gidaghanon, Tax rate, Nakuha: Subtotal, buhis, Total.
Lakang 3: Account & Feedback
Naa kay account? (Oo/Dili) Kung Oo → username + password, gikinahanglan ang duha. Kung Dili → email nakolekta na sa lakang 1.
Rating sa katagbawan (1–5) Kung ≥ 4 → pangutana og “Unsay imong ganahan?” Kon ≤ 2 → pangutan-a ang “Unsay atong mapauswag?”
Lakang 4: Pagrepaso
Makita lang kung total >= 100 Katapusan nga pagsumite.
Dili kini sobra. Apan igo na nga ibutyag ang mga kalainan sa arkitektura. Bahin 1: Component-Driven (React Hook Form + Zod) Pag-instalar npm instalar react-hook-form zod @hookform/resolvers @tanstack/react-query
Zod Schema Magsugod kita sa eskema sa Zod, tungod kay kana kasagaran diin ang porma sa porma matukod. Para sa unang duha ka lakang — personal nga mga detalye ug order inputs — ang tanan prangka: gikinahanglang mga kuwerdas, mga numero nga adunay mga minimum, ug usa ka enum. Ang makapaikag nga bahin magsugod sa diha nga ikaw mosulay sa pagpahayag sa kondisyon nga mga lagda.
import {z} gikan sa "zod";
export const formSchema = z.object({firstName: z.string().min(1, "Kinahanglan"), email: z.string().email("Invalid email"), presyo: z.number().min(0), quantity: z.number().min(1), taxRate: z.number(), hasAccount:z.enumNo. password: z.string().optional(), katagbawan: z.number().min(1).max(5), positiveFeedback: z.string().optional(), improvementFeedback: z.string().optional(),}).superRefine((data, ctx) => {kon (data.hasAccount === "Oo") {kon (!data.username) {scode(!data.username) {s. ["username"], mensahe: "Kinahanglan" }); } if (!data.password || data.password.length < 6) { ctx.addIssue({ code: "custom", path: ["password"], message: "Min 6 characters" } }
kon (data.satisfaction >= 4 && !data.positiveFeedback) {ctx.addIssue({code: "custom", path: ["positiveFeedback"], message: "Palihug ipaambit ang imong nagustohan"}); }
kon (data.satisfaction <= 2 && !data.improvementFeedback) {ctx.addIssue({code: "custom", path:["improvementFeedback"], mensahe: "Palihug sultihi mi kung unsay angay pauswagon" }); }});
export type nga FormData = z.infer
Matikdi nga ang username ug password gi-type isip opsyonal() bisan og kini gikinahanglan sa kondisyon tungod kay ang Zod's type-level schema naghulagway sa porma sa butang, dili ang mga lagda nga nagdumala kung ang mga field importante. Ang kinahanglanon nga kondisyon kinahanglan nga magpuyo sa sulod sa superRefine, nga modagan pagkahuman mapamatud-an ang porma ug adunay access sa tibuuk nga butang. Kana nga panagbulag dili usa ka sayup; mao ra kini ang gidesinyo sa himan: ang superRefine kung diin moadto ang cross-field logic kung dili kini mapahayag sa istruktura sa schema mismo. Ang talagsaon usab dinhi mao ang wala ipahayag niini nga schema. Wala kini konsepto sa mga panid, walay konsepto kung unsang mga field ang makita kung asa nga punto, ug walay konsepto sa nabigasyon. Kanang tanan magpuyo sa laing dapit. Porma nga Component
import {useForm, useWatch } gikan sa "react-hook-form";import {zodResolver} gikan sa "@hookform/resolvers/zod";import {useMutation} gikan sa "@tanstack/react-query";import {useState, useMemo} gikan sa "react";import {formSchema, type ang FormData}
const STEPS = ["detalye", "order", "account", "review"];
type OrderPayload = FormData & {subtotal: numero; buhis: numero; total: numero };
export function RHFMultiStepForm() {const [lakang, setStep] = useState(0);
const mutation = useMutation({ mutationFn: async (payload: OrderPayload) => { const res = maghulat sa pagkuha ("/api/mga order", { pamaagi: "POST", mga ulohan: { "Content-Type": "application/json" }, lawas: JSON.stringify(payload), }); kung (!res.ok) ilabay ang bag-ong Error("Napakyas sa pagsumite"); ibalik ang res.json(); }, });
const {rehistro, kontrol, handleSubmit, formState: {mga sayop}, } = useForm
ibalik (
);}Tan-awa ang Pen SurveyJS-03-RHF [gisawang] sa unom nga pagkapuo. Daghan kaayo ang nahitabo dinhi, ug angayan nga maghinayhinay aron mahibal-an kung diin natapos ang mga butang.
Ang nakuha nga mga kantidad - subtotal, buhis, total - gikalkula sa sangkap pinaagi sa useWatch ug useMemo tungod kay nagdepende kini sa mga live field value ug wala nay laing natural nga lugar para kanila. Ang visibility nga mga lagda alang sa username, password, positiveFeedback, ug improvementFeedback live sa JSX isip inline nga mga kondisyon. Ang lohika sa paglaktaw sa lakang — ang panid sa pagrepaso makita ra kung ang kinatibuk-an >= 100 — na-embed sa showSubmit variable ug ang kondisyon sa paghubad sa lakang 3. Ang nabigasyon mismo usa lang ka useState counter nga among gidugangan sa mano-mano. Ang React Query nagdumala sa mga pagsulay pag-usab, pag-cache, ug pagka-invalidation. Gitawag lang sa porma ang mutation.mutate nga adunay validated data.
Walay usa niini nga sayop, per se. Kini usa pa ka idiomatic nga React, ug ang sangkap labi ka pasundayag salamat sa kung giunsa ang paglainlain sa RHF pag-usab. Apan kung imong ihatag kini sa usa ka tawo nga wala pa magsulat niini ug hangyoa sila nga ipasabut kung unsa nga mga kondisyon ang makita sa panid sa pagrepaso, kinahanglan nila nga i-trace pinaagi sa showSubmit, ang lakang 3 render nga kondisyon, ug ang nav button nga lohika - tulo ka managlahing lugar - aron matukod pag-usab ang usa ka lagda nga mahimo unta nga gipahayag sa usa ka linya. Ang porma molihok, oo, apan ang pamatasan dili gyud masusi ingon usa ka sistema. Kinahanglang ipatuman kini sa mental. Labaw sa tanan, ang pagbag-o niini nanginahanglan pag-apil sa engineering. Bisan ang gamay nga tweak, sama sa pag-adjust kung ang lakang sa pagrepaso nagpakita, nagpasabut nga pag-edit sa sangkap, pag-update sa validation, pag-abli sa usa ka hangyo sa pagbitad, paghulat alang sa pagrepaso, ug pag-deploy pag-usab. Bahin 2: Gimaneho sa Schema (SurveyJS) Karon magtukod kita sa parehas nga dagan gamit ang usa ka schema. Pag-instalar npm i-install ang survey-core survey-react-ui @tanstack/react-query
survey-coreAng MIT-licensed platform-independent runtime engine nga nagpalihok sa paghubad sa porma sa SurveyJS - ang bahin nga among giatiman dinhi. Nagkinahanglan kini og JSON schema, nagtukod og internal nga modelo gikan niini, ug nagdumala sa tanang butang nga mopuyo sa imong React component: pag-evaluate sa visibility expressions, computing derived values, pagdumala sa page state, tracking validation, ug pagdesisyon kon unsay gipasabot sa "kompleto" nga gihatag kung unsang mga panid ang tinuod nga gipakita.
survey-react-uiAng UI / rendering layer nga nagkonektar niana nga modelo sa React. Kini usa ka sangkap nga
Mag-uban, gihatagan ka nila og usa ka bug-os nga magamit, multi-panid nga porma nga runtime nga walay pagsulat sa usa ka linya sa kontrol nga dagan. Ang format sa schema mismo, sama sa giingon kaniadto, usa lamang ka JSON - walay DSL o bisan unsang proprietary. Mahimo nimong i-inline kini, i-import kini gikan sa usa ka file, kuhaon kini gikan sa usa ka API, o itago kini sa usa ka column sa database ug i-hydrate kini sa runtime. Parehas nga Porma, Ingon sa Data Ania ang parehas nga porma, niining higayona gipahayag ingon usa ka butang nga JSON. Gihubit sa schema ang tanan: istruktura, pag-validate, mga lagda sa visibility, nakuha nga mga kalkulasyon, pag-navigate sa panid - ug ihatag kini sa usa ka Modelo nga nagtimbang-timbang niini sa oras sa pagdagan. Ania kung unsa ang hitsura sa tibuuk:
export const surveySchema = {titulo: "Order Flow", showProgressBar: "top", mga panid: [ {ngalan: "detalye", elemento: [ { type: "text", ngalan: "firstName", isRequired: true }, {type: "text", ngalan: "email", inputType: "email", isRequired: [{type: "text" }] } ] }, {ngalan: "order", elemento: [ { type: "text", ngalan: "presyo", inputType: "numero", defaultValue: 0 }, { type: "text", ngalan: "quantity", inputType: "numero", defaultValue: 1 }, {type: "dropdown",ngalan: "TaxRate", defaultValue: 0.1, mga pagpili: [ {value: 0.05, text: "5%" }, {value: 0.1, text: "10%" }, {value: 0.15, text: "15%" } ] }, {type: "expression", ngalan: "{price" }": "expression", ngalan: "tax", expression: "{subtotal} {taxRate}" }, {type: "expression", name: "total", expression: "{subtotal} + {tax}" } ] }, {name: "account", mga elemento: [ {type: "radiogroup", ngalan: "adunay]Account", mga pagpili: "Kon",": "Noble type" "{hasAccount} = 'Oo'", isKinahanglan: tinuod }, { type: "text", ngalan: "password", inputType: "password", visibleIf: "{hasAccount} = 'Yes'", isRequired: true, validators: [{ type: "text", minLength: 6, text: "Min 6 nga mga karakter", }: "tistion:" 1, rateMax: 5 }, { type: "comment", ngalan: "positiveFeedback", visibleIf: "{satisfaction} >= 4" }, {type: "comment", name: "improvementFeedback", visibleIf: "{satisfaction} <= 2" } ] }, {name: "review", visible If: {name: "review", 0} >: ]};
Itandi kini sa RHF nga bersyon sa makadiyot.
Ang superRefine block nga gikinahanglan sa kondisyon nga username ug password wala na. visibleIf: "{hasAccount} = 'Oo'" inubanan sa isRequired: ang true nagdumala sa duha ka mga kabalaka, sa natad mismo, diin imong gilauman nga makit-an kini. Ang useWatch + useMemo chain nga nag-compute sa subtotal, tax, ug total gipulihan sa tulo ka expression fields nga nag-refer sa usag usa pinaagi sa ngalan. Ang kondisyon sa panid sa pagrepaso, nga sa RHF nga bersyon matukod pag-usab pinaagi sa pagsubay pinaagi sa showSubmit, ang lakang 3 render nga sanga. Ug sa katapusan, ang nav button logic usa ka visibleIf nga kabtangan sa butang nga panid.
Ang sama nga lohika anaa. Kini ra nga ang schema naghatag kini usa ka lugar nga puy-an kung diin kini makita nga nag-inusara, imbes nga mikaylap sa tibuuk nga sangkap. Usab, timan-i nga ang schema naggamit ug tipo: 'expression' para sa subtotal, buhis, ug total. Ang ekspresyon kay read-only ug gigamit sa panguna aron ipakita ang mga kalkulado nga kantidad. Gisuportahan usab sa SurveyJS ang tipo: 'html' alang sa static nga sulud, apan alang sa mga kalkulado nga kantidad, ang ekspresyon mao ang husto nga kapilian. Karon alang sa React nga bahin. Pag-render ug Pagsumite Simple kaayo. Wire onComplete sa imong API sa samang paagi — pinaagi sa useMutation o plain fetch:
import {useState, useEffect, useRef } gikan sa "react";import {useMutation} gikan sa "@tanstack/react-query";import {Modelo} gikan sa "survey-core";import {Survey} gikan sa "survey-react-ui";import "survey-core/survey-core.css";
export function SurveyForm() { const [modelo] = useState(() => bag-ong Model(surveySchema));
const mutation = useMutation({ mutationFn: async (data) => { const res = maghulat sa pagkuha ("/api/mga order", { pamaagi: "POST", mga ulohan: { "Content-Type": "application/json" }, lawas: JSON.stringify(data), }); kung (!res.ok) ilabay ang bag-ong Error("Napakyas sa pagsumite"); ibalik ang res.json(); }, });
const mutationRef = useRef(mutation); mutationRef.current = mutation; useEffect(() => {const handler = (sender) => mutationRef.current.mutate(sender.data);model.onComplete.add(handler);balik() => model.onComplete.remove(handler); }, [modelo]); // gilikayan sa ref ang pagrehistro pag-usab sa handler matag render (mga pagbag-o sa pagkatawo sa butang nga mutation)
balik (
<>
Tan-awa ang Pen SurveyJS-03-SurveyJS [gisawang] pinaagi sa sixtheextinction.
onComplete fires kung ang user makaabot sa katapusan sa katapusang makita nga panid. Mao nga kung ang kinatibuk-an dili gyud molapas sa 100 ug ang panid sa pagrepaso gilaktawan, kini nagpadayon sa husto tungod kay ang SurveyJS nag-evaluate sa visibility sa wala pa magdesisyon kung unsa ang gipasabut sa "katapusan nga panid". Unya, ang sender.data naglangkob sa tanan nga mga tubag uban sa mga kalkulado nga kantidad (subtotal, buhis, total) isip mga first-class nga field, mao nga ang API payload parehas sa unsay gi-assemble sa RHF version sa onSubmit. AngAng mutationRef nga pattern mao ra ang imong maabot bisan asa nga kinahanglan nimo ang usa ka lig-on nga tigdumala sa panghitabo sa usa ka kantidad nga nagbag-o sa matag render - wala’y piho nga SurveyJS bahin niini.
Ang React component wala nay sulod sa bisan unsang business logic. Walay useWatch, walay conditional JSX, walay step counter, walay useMemo chain, walay superRefine. Ang reaksyon mao ang pagbuhat kung unsa ang maayo niini: paghubad sa usa ka sangkap ug pag-wire niini sa usa ka tawag sa API. Unsa ang Gibalhin sa Reaksyon?
Kabalaka RHF Stack SurveyJS Makita Mga sanga sa JSX makitaKon Nakuha nga mga bili gamita Watch / useMemo ekspresyon Mga lagda sa cross-field superRefine Mga kondisyon sa eskema Nabigasyon lakang nga estado Makita ang panid kung Lokasyon sa lagda Giapod-apod sa mga file Nakasentro sa eskema
Ang nagpabilin sa React mao ang layout, pag-istilo, pagsumite sa mga wiring, ug pag-integrate sa app, nga sa ato pa, ang mga butang nga React kay gidisenyo gyud. Ang tanan nabalhin sa schema, ug tungod kay ang schema usa lang ka butang nga JSON, mahimo kini nga tipigan sa usa ka database, gi-bersyon nga independente sa imong code sa aplikasyon, o gi-edit pinaagi sa internal tooling nga wala magkinahanglan usa ka pag-deploy. Ang usa ka manedyer sa produkto nga kinahanglan magbag-o sa threshold nga nag-aghat sa panid sa pagrepaso makahimo niana nga dili mahikap ang sangkap. Kana usa ka makahuluganon nga kalainan sa operasyon alang sa mga koponan diin ang pamatasan kanunay nga nagbag-o ug dili kanunay gimaneho sa mga inhenyero. Kanus-a Gamiton ang Matag Pamaagi? Ania ang usa ka maayo nga lagda nga magamit alang kanako: hunahunaa ang pagtangtang sa porma sa hingpit. Unsay mawala nimo?
Kung kini mga screen, gusto nimo ang mga porma nga gimaneho sa sangkap. Kung kini ang lohika sa negosyo, sama sa mga threshold, mga lagda sa pagsanga, ug mga kinahanglanon sa kondisyon nga nag-encode sa tinuud nga mga desisyon, gusto nimo ang usa ka makina sa eskema.
Sa susama, kung ang mga pagbag-o nga moabut sa imong dalan kasagaran bahin sa mga label, field, ug layout, ang RHF magsilbi kanimo nga maayo. Kung kini mahitungod sa mga kondisyon, resulta, ug mga lagda nga kinahanglan nga i-adjust sa imong ops o legal nga team sa Martes sa hapon nga walay pag-file og tiket, ang modelo sa schema sa SurveyJS mao ang mas matinud-anon nga angay. Kining duha ka mga pamaagi dili gyud sa kompetisyon sa usag usa. Gitubag nila ang lainlaing mga klase sa mga problema, ug ang sayup nga angay likayan mao ang dili pagtugma sa abstraction sa gibug-aton sa lohika - pagtratar sa usa ka sistema sa pagmando sama sa usa ka sangkap tungod kay kana ang pamilyar nga himan, o pagkab-ot sa usa ka makina sa palisiya tungod kay ang usa ka porma mitubo sa tulo ka mga lakang ug nakakuha usa ka kondisyon nga natad. Ang porma nga among gitukod dinhi naglingkod duol sa utlanan nga tinuyo, komplikado nga igo aron ibutyag ang kalainan apan dili kaayo hilabihan nga ang pagtandi ingon og rigged. Kadaghanan sa mga tinuod nga porma nga nahimong dili magamit sa imong codebase lagmit naglingkod duol sa parehas nga utlanan, ug ang pangutana kasagaran kung adunay bisan kinsa nga nagngalan kung unsa sila. Gamita ang React Hook Form + Zod kung:
Ang mga porma kay CRUD-oriented; Ang lohika mabaw ug gimaneho sa UI; Ang mga inhenyero nanag-iya sa tanang kinaiya; Ang backend nagpabilin nga tinubdan sa kamatuoran.
Gamita ang SurveyJS kung:
Mga porma nga nag-encode sa mga desisyon sa negosyo; Ang mga lagda nag-uswag nga independente sa UI; Ang lohika kinahanglan nga makita, maaudit, o may bersyon; Ang dili mga inhenyero nag-impluwensya sa pamatasan; Ang parehas nga porma kinahanglan nga modagan sa daghang mga frontend.