Ин мақола аз ҷониби SurveyJS сарпарастӣ шудааст Модели равонӣ вуҷуд дорад, ки аксари таҳиягарони React бидуни ҳеҷ гоҳ онро бо овози баланд муҳокима мекунанд. Ин шаклҳо бояд ҳамеша ҷузъҳо бошанд. Ин маънои онро дорад, ки стек ба монанди:
Шакли Hook React барои давлати маҳаллӣ (ҳадди ақали такрорӣ, бақайдгирии майдони эргономикӣ, ҳамкории императивӣ). Zod барои тасдиқ (дурустии вуруд, санҷиши сарҳад, таҳлили бехатарии навъи). React Query барои пуштибонӣ: пешниҳод, кӯшишҳои такрорӣ, кэш, ҳамоҳангсозии сервер ва ғайра.
Ва барои аксарияти шаклҳо - экранҳои воридшавии шумо, саҳифаҳои танзимоти шумо, модальҳои 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: Компонентҳо асосёфта (Формаи Hook React + Zod) Насбкунӣ npm насб кардани react-hook-form zod @hookform/resolvers @tanstack/react-query
Схемаи Зод Биёед бо схемаи Zod оғоз кунем, зеро одатан дар он ҷо шакли шакл муқаррар карда мешавад. Барои ду қадами аввал - тафсилоти шахсӣ ва вурудоти фармоиш - ҳама чиз осон аст: сатрҳои зарурӣ, рақамҳо бо ҳадди аққал ва рақам. Қисми ҷолиб вақте оғоз мешавад, ки шумо кӯшиш мекунед, ки қоидаҳои шартиро баён кунед.
воридоти { z } аз "zod";
содироти const formSchema = z.object({ firstName: z.string().min(1, "Талаб карда мешавад"), почтаи электронӣ: z.string().email("Почтаи беэътибор"), нарх: z.number().min(0), микдор: z.number().min(1), taxRate: z.number(), hasAccount(), name user(), "z":" z.string().optional(), гузарвожа: z.string().optional(), қаноатмандӣ: z.number().min(1).макс(5), мусбӣFeedback: z.string().ixtiyari(), improvementFeedback: z.string().optional(),}).superRefine((маълумот, ctxda==)(маълумот, ctxda=agar=s.A {agar count) =" {A. (!data.username) { ctx.addIssue({ code: "custom", path: ["username"], message: "Талаб карда мешавад" }); }
if (data.satisfaction >= 4 && !data.positiveFeedback) { ctx.addIssue({ код: "custom", path: ["positiveFeedback"], паём: "Лутфан он чизеро, ки ба шумо маъқул буд, мубодила кунед" }); }
агар (data.satisfaction <= 2 && !data.improvementFeedback) { ctx.addIssue ({ код: "муштарӣ", роҳ:["improvementFeedback"], паём: "Лутфан, ба мо бигӯед, ки чӣ бояд беҳтар шавад" }); }});
навъи содирот FormData = z.infer
Аҳамият диҳед, ки номи корбар ва парол ҳамчун ихтиёрӣ () чоп карда мешаванд, гарчанде ки онҳо шартан талаб карда мешаванд, зеро схемаи сатҳи навъи Zod шакли объектро тавсиф мекунад, на қоидаҳои танзимкунандаи вақте ки майдонҳо муҳиманд. Талаботи шартӣ бояд дар дохили superRefine зиндагӣ кунад, ки пас аз тасдиқи шакл кор мекунад ва ба объекти пурра дастрасӣ дорад. Ин ҷудоӣ камбудие нест; ин маҳз ҳамон чизест, ки асбоб барои он тарҳрезӣ шудааст: superRefine он ҷоест, ки мантиқи байнисоҳавӣ ҷойгир аст, вақте ки онро дар худи сохтори схема ифода кардан мумкин нест. Он чизе, ки дар ин ҷо низ ҷолиб аст, он чизест, ки ин схема ифода намекунад. Он мафҳуми саҳифаҳо надорад, мафҳуми он, ки кадом майдонҳо дар кадом нуқта намоён мешаванд ва мафҳуми навигатсия вуҷуд надорад. Ҳамаи ин дар ҷои дигар зиндагӣ хоҳад кард. Компоненти форма
import { useForm, useWatch } аз "react-hook-form";import { zodResolver } аз "@hookform/resolvers/zod";import { useMutation } аз "@tanstack/react-query";import { useState, useMemo } аз "react"; import { formSchema} аз FormSchema, навъи ";";
const STEPS = ["тафсилот", "фармоиш", "ҳисоб", "баррасӣ"];
навъи OrderPayload = FormData & { subtotal: рақам; андоз: рақам; ҷамъ: адад };
Функсияи содироти RHFMultiStepForm () { const [қадам, setStep] = useState (0);
const мутатсия = useMutation({ mutationFn: асинхронӣ (борбор: OrderPayload) => { const res = интизори гирифтани овардан ("/api/orders", { усул: "POST", сарлавҳаҳо: { "Content-Type": "application/json" }, бадан: JSON.stringify (борбори), }); агар (!res.ok) партоед Хатои нав("Фарол кардан муяссар нашуд"); баргардонидани res.json(); }, });
const { регистр, назорат, handleSubmit, formState: { хатоҳо }, } = useForm
бозгашт (
);Ба Pen SurveyJS-03-RHF [forked] аз ҷониби sixthextinction нигаред. Дар ин ҷо бисёр чизҳо рӯй дода истодаанд ва барои дидани он ки корҳо ба куҷо расиданд, суст шудан лозим аст.
Арзишҳои ҳосилшуда - зермаҷмӯӣ, андоз, ҷамъ - дар ҷузъ тавассути useWatch ва useMemo ҳисоб карда мешаванд, зеро онҳо аз арзишҳои майдони зинда вобастаанд ва барои онҳо ҷои дигари табиӣ вуҷуд надорад. Қоидаҳои намоён барои номи корбар, парол, мусбӣFeedback ва такмилдиҳииFeedback дар JSX ҳамчун шартҳои дохилӣ зиндагӣ мекунанд. Мантиқи гузариш ба қадам - саҳифаи барраси танҳо вақте пайдо мешавад, ки дар маҷмӯъ >= 100 аст - ба тағирёбандаи showSubmit ва ҳолати намоиш дар қадами 3 ворид карда мешавад. Навигатсия танҳо як ҳисобкунаки useState аст, ки мо онро дастӣ афзоиш медиҳем. React Query кӯшишҳои такрорӣ, кэшкунӣ ва беэътиборро идора мекунад. Шакл танҳо бо маълумоти тасдиқшуда mutation.mutate -ро даъват мекунад.
Ҳеҷ кадоме аз ин нодуруст нест, худаш. Ин ҳанӯз ҳам реаксияи идиоматикӣ аст ва ҷузъ ба туфайли он, ки чӣ тавр RHF аз нав изолятсия мекунад, хеле самаранок аст. Аммо агар шумо инро ба касе медодед, ки онро нанавишта буд ва аз онҳо бипурсед, ки дар кадом шароит пайдо шудани саҳифаи баррасиро шарҳ диҳанд, онҳо бояд тавассути showSubmit, шарти намоиши қадами 3 ва мантиқи тугмаи нав - се ҷои алоҳида - барои барқарор кардани қоидае, ки метавонистанд дар як сатр зикр шаванд, пайгирӣ кунанд. Шакл кор мекунад, бале, аммо рафтор аслан ҳамчун система тафтиш карда намешавад. Он бояд рӯҳан иҷро карда шавад. Муҳимтар аз ҳама, тағир додани он ҷалби муҳандисонро талаб мекунад. Ҳатто як tweak хурд, ба монанди тасҳеҳ вақте ки қадами бознигарӣ нишон дода мешавад, маънои таҳрир кардани ҷузъ, навсозии тасдиқ, кушодани дархости кашидан, интизории баррасӣ ва ҷойгиркунии дубора дорад. Қисми 2: Схема асосёфта (SurveyJS) Акнун биёед ҳамон ҷараёнро бо истифода аз схема созем. Насбкунӣ npm насб кардани anket-core survey-react-ui @tanstack/react-query
survey-coreThe муҳаррики вақти корӣ аз платформаи мустақили аз ҷониби MIT литсензияшуда, ки ба коркарди шаклҳои SurveyJS қувват мебахшад - қисме, ки мо дар ин ҷо ғамхорӣ мекунем. Он схемаи JSON-ро мегирад, аз он модели дохилиро месозад ва ҳама чизеро, ки дар ҷузъҳои React-и шумо зиндагӣ мекунад, идора мекунад: арзёбии ифодаҳои намоён, ҳисоб кардани арзишҳои ҳосилшуда, идоракунии ҳолати саҳифа, пайгирии санҷиш ва муайян кардани маънои "пурра" бо назардошти он ки саҳифаҳо воқеан нишон дода шудаанд.
anket-react-uiҚабати UI / рендеринг, ки ин моделро ба React мепайвандад. Он аслан як ҷузъи
Якҷоя, онҳо ба шумо вақти пурраи функсионалии бисёрсаҳифаро бидуни навиштани як сатри ҷараёни назорат медиҳанд. Худи формати схема, тавре ки қаблан гуфта шуда буд, танҳо як JSON аст - ҳеҷ DSL ё ягон чизи хусусӣ. Шумо метавонед онро ба сатр ворид кунед, онро аз файл ворид кунед, аз API гиред ё онро дар сутуни махзани маълумот нигоҳ доред ва дар вақти корӣ онро обдор кунед. Ҳамон шакл, ҳамчун маълумот Ин ҳамон шакл аст, ки ин дафъа ҳамчун объекти JSON ифода шудааст. Схема ҳама чизро муайян мекунад: сохтор, тасдиқ, қоидаҳои намоён, ҳисобҳои ҳосилшуда, паймоиши саҳифа - ва онро ба Моделе медиҳад, ки онро дар вақти корӣ арзёбӣ мекунад. Ин аст он чизе ки пурра ба назар мерасад:
export const surveySchema = { унвон: "Ҷараёни Тартиб", showProgressBar: "боло", саҳифаҳо: [ {ном: "тафсилот", элементҳо: [ {навъ: "матн", ном: "name", isRequired: ҳақиқӣ }, {навъи: "матн", ном: "почтаи электронӣ", inputType: "почтаи электронӣ", isTaleb: "матн: ҳақиқӣ:" почтаи электронӣ" }] } ] }, { ном: "тартиб", элементҳо: [ {навъ: "матн", ном: "нарх", inputType: "рақам", defaultValue: 0 }, {навъ: "матн", ном: "микдор", inputType: "рақам", defaultValue: 1 }, {навъи: "афтанда",ном: "taxRate", defaultValue: 0,1, интихобҳо: [ {арзиш: 0,05, матн: "5%" }, { арзиш: 0,1, матн: "10%" }, { арзиш: 0,15, матн: "15%" } ] }, {навъ: "ифода", ном: "{anttotal", навъи {}}," "ифода", ном: "андоз", ифода: "{subtotal} {taxRate}" }, {навъ: "ифода", ном: "томаъ", ифода: "{субмаҷмӯа} + {андоз}" } ] }, { ном: "ҳисоб", элементҳо: [ {навъ: "радиогурӯҳ", ном: "hasAccount] [навъ:" ":" {":t", интихобҳо ном: "номи корбар", visibleIf: "{hasAccount} = 'Бале'", isRequired: true }, { type: "text", name: "password", inputType: "password", visibleIf: "{hasAccount} = 'Ha'", isRequired: true, validators: [{hasAccount} = 'Ҳа': 6. аломатҳо" }] }, { навъи: "рейтинг", ном: "қаноатмандӣ", rateMin: 1, rateMax: 5 }, {навъ: "шарҳ", ном: "позитивии Feedback", visibleIf: "{қаноатмандӣ} >= 4" }, {навъи: "шарҳ", ном: "improvementFeed:" <{visibleIf:" ] }, { name: "review", visibleIf: "{total} >= 100", элементҳо: [] } ]};
Як лаҳза инро бо версияи RHF муқоиса кунед.
Блоки superRefine, ки шартан номи корбар ва паролро талаб мекард, нест шуд. visibleIf: "{hasAccount} = 'Ҳа'" дар якҷоягӣ бо isRequired: true ҳарду нигарониро дар худи майдон, ки шумо интизор будед, пайдо кунед, ҳал мекунад. Занҷираи useWatch + useMemo, ки зермаҷмӯ, андоз ва ҷамъро ҳисоб кардааст, бо се майдони ифодаи иваз карда мешавад, ки ба ҳамдигар бо ном ишора мекунанд. Ҳолати саҳифаи барраси, ки дар версияи RHF танҳо тавассути пайгирӣ тавассути showSubmit, марҳилаи 3-юми визуалӣ барқароршаванда буд. Ва ниҳоят, мантиқи тугмаи нав як хосияти ягонаи visibleIf дар объекти саҳифа мебошад.
Ҳамин мантиқ вуҷуд дорад. Ин танҳо он аст, ки схема ба он ҷои зиндагӣ медиҳад, ки он дар алоҳидагӣ намоён аст, на дар тамоми ҷузъ паҳн. Инчунин, қайд кунед, ки схема навъи истифода мебарад: "ифода" барои зермаҷмӯӣ, андоз ва умумӣ. Ифода танҳо барои хондан аст ва асосан барои намоиши арзишҳои ҳисобшуда истифода мешавад. SurveyJS инчунин намуди: 'html' -ро барои мундариҷаи статикӣ дастгирӣ мекунад, аммо барои арзишҳои ҳисобшуда ифода интихоби дуруст аст. Ҳоло барои ҷониби React. Намоиш ва пешниҳод Хеле содда. Wire onComplete -ро ба API-и худ ба ҳамон тарз пайваст кунед - тавассути useMutation ё оддӣ гирифтан:
import { useState, useEffect, useRef } аз "react";import { useMutation } аз "@tanstack/react-query"; import { Model } аз "survey-core";импорт { Survey } аз "survey-react-ui";импорт "survey-core/survey-core.css";
Функсияи содироти SurveyForm() { const [model] = useState(() => Модели нав(surveySchema));
const мутатсия = useMutation({ mutationFn: асинх (маълумот) => { const res = интизори гирифтани овардан ("/api/orders", { усул: "POST", сарлавҳаҳо: { "Content-Type": "application/json" }, бадан: JSON.stringify (маълумот), }); агар (!res.ok) партоед Хатои нав("Фарол кардан муяссар нашуд"); баргардонидани res.json(); }, });
const mutationRef = useRef(мутация); mutationRef.current = мутатсия; useEffect(() => { const handler = (фиристанда) => mutationRef.current.mutate(sender.data); model.onComplete.add(andler); return () => model.onComplete.remove(andler);}, [модел]); // ref аз сабти дубораи коркардкунанда дар ҳар як намоиш худдорӣ мекунад (тағйирёбии шахсияти объекти мутатсия)
бозгашт ( <> <Модели пурсиш={model} /> {mutation.isError &&
Ба Pen SurveyJS-03-SurveyJS [forked] аз ҷониби sixthextinction нигаред.
onComplete вақте оташ мезанад, ки корбар ба охири саҳифаи намоёни охирин мерасад. Ҳамин тавр, агар маҷмӯа ҳеҷ гоҳ аз 100 нагузарад ва саҳифаи барраси гузаронида шавад, он ба ҳар ҳол дуруст оташ мезанад, зеро SurveyJS намоёниро пеш аз муайян кардани маънои "саҳифаи охирин" арзёбӣ мекунад. Сипас, sender.data дорои ҳама ҷавобҳоро дар баробари арзишҳои ҳисобшуда (зершуморӣ, андоз, умумӣ) ҳамчун майдонҳои дараҷаи аввал, аз ин рӯ, сарбории API ба он чизе, ки версияи RHF дар onSubmit дастӣ ҷамъ оварда шудааст, шабеҳ аст. ДарНамунаи mutationRef ҳамон як намунаест, ки шумо дар ҳама ҷое мерасед, ба шумо як коркардкунандаи рӯйдодҳои устувор аз болои арзише лозим аст, ки дар ҳар як рендер тағир меёбад - ҳеҷ чиз ба SurveyJS хос нест.
Ҷузъи React дигар умуман мантиқи тиҷорӣ надорад. Ягон useWatch, JSX-и шартӣ, ҳисобкунаки қадамҳо, занҷири useMemo ва superRefine вуҷуд надорад. React кореро иҷро мекунад, ки дар асл хуб аст: додани ҷузъ ва пайваст кардани он ба занги API. Чӣ аз реаксия берун шуд?
Ташвиш Stack RHF SurveyJS Намоиш филиалҳои JSX visibleIf Арзишҳои ҳосилшуда useWatch / useMemo ифода Қоидаҳои байнисоҳавӣ супертозакунӣ Шароити схема Навигатсия ҳолати қадам Саҳифа visibleIf Ҷойгиршавии қоида Дар байни файлҳо тақсим карда мешавад Дар схема марказонида шудааст
Он чизе, ки дар React боқӣ мемонад, тарҳ, ороиш, ноқилҳои пешниҳод ва ҳамгироии барномаҳост, яъне он чизест, ки React воқеан барои он тарҳрезӣ шудааст. Ҳама чизи боқимонда ба схема кӯчонида шуданд ва азбаски схема танҳо як объекти JSON аст, онро метавон дар махзани маълумот нигоҳ дошт, новобаста аз коди замимаи шумо нусхабардорӣ карда шавад ё тавассути асбобҳои дохилӣ бидуни ниёз ба ҷойгиркунӣ таҳрир карда шавад. Менеҷери маҳсулоте, ки бояд ҳадди ниҳоиеро, ки саҳифаи баррасиро ба вуҷуд меорад, тағир диҳад, метавонад ин корро бидуни ламс кардани ҷузъ анҷом диҳад. Ин як фарқияти назарраси амалиётӣ барои гурӯҳҳое аст, ки рафтори шакл зуд-зуд таҳаввул меёбад ва на ҳамеша аз ҷониби муҳандисон идора карда мешавад. Ҳар як равишро кай бояд истифода кард? Ин як қоидаи хубест, ки барои ман кор мекунад: тасаввур кунед, ки формаро пурра нест кунед. Шумо чиро аз даст медиҳед?
Агар он экранҳо бошад, шумо мехоҳед шаклҳои ба компонент асосёфта дошта бошед. Агар он мантиқи тиҷорӣ бошад, ба монанди ҳадди ниҳоӣ, қоидаҳои шоха ва талаботҳои шартӣ, ки қарорҳои воқеиро рамзгузорӣ мекунанд, шумо муҳаррики схемаро мехоҳед.
Ба ҳамин монанд, агар тағиротҳое, ки ба шумо меоянд, асосан дар бораи тамғакоғазҳо, майдонҳо ва тарҳбандӣ бошанд, RHF ба шумо хуб хидмат мекунад. Агар онҳо дар бораи шароитҳо, натиҷаҳо ва қоидаҳое бошанд, ки амалиёти шумо ё гурӯҳи ҳуқуқии шумо бояд дар нимаи рӯзи сешанбе бидуни пешниҳоди чипта танзим кунанд, модели схема бо SurveyJS дурусттар аст. Ин ду равиш аслан бо ҳам рақобат намекунанд. Онҳо синфҳои гуногуни мушкилотро ҳал мекунанд ва иштибоҳе, ки бояд пешгирӣ кард, мувофиқат накардани абстраксия ба вазни мантиқ аст - муносибат кардани системаи қоида ба монанди ҷузъ, зеро ин асбоби шинос аст ё расидан ба муҳаррики сиёсат, зеро шакл ба се зина расидааст ва майдони шартиро ба даст овард. Форме, ки мо дар ин ҷо сохтаем, дидаву дониста дар наздикии сарҳад ҷойгир аст ва ба қадри кофӣ мураккаб аст, ки фарқиятро фош кунад, аммо на он қадар шадид, ки муқоиса бо тақаллуб эҳсос мешавад. Аксари шаклҳои воқеие, ки дар базаи коди шумо ноустувор шудаанд, эҳтимолан дар наздикии ҳамон сарҳад ҷойгиранд ва савол одатан танҳо ин аст, ки оё касе онҳоро номбар кардааст, ки онҳо воқеан ҳастанд. Ҳангоми: React Hook Form + Zod-ро истифода баред:
Шаклҳо ба CRUD нигаронида шудаанд; Мантиқ суст аст ва ба UI асос ёфтааст; Муҳандисон тамоми рафторро доранд; Backend манбаи ҳақиқат боқӣ мемонад.
SurveyJS-ро ҳангоми:
Шаклҳо қарорҳои тиҷоратиро рамзгузорӣ мекунанд; Қоидаҳо новобаста аз UI инкишоф меёбанд; Мантиқ бояд намоён, тафтишшаванда ё нусхабардорӣ бошад; Ба рафтори муҳандисон таъсир мерасонад; Як шакл бояд дар якчанд фронтҳо кор кунад.