متن خبر

نحوه اعتبار سنجی فرم ها با Zod و React-Hook-Form

نحوه اعتبار سنجی فرم ها با Zod و React-Hook-Form

شناسهٔ خبر: 443686 -




فرم ها به شما این امکان را می دهند که داده های کاربر را در وب سایت ها و برنامه های خود جمع آوری کنید. و اعتبارسنجی برای تضمین ایمنی نوع و قالب مناسب برای داده های جمع آوری شده ضروری است. شما می توانید اعتبارسنجی را در سمت کلاینت و سرور برنامه انجام دهید.

اینجاست که Zod و React-Hook-Form به عنوان یک دوتایی پویا وارد می شوند و آماده هستند تا فرم های شما را به سطح بعدی برسانند.

Zod یک کتابخانه اعتبار سنجی است که یک نحو مختصر و گویا برای تعریف طرحواره های داده ارائه می دهد و آن را به یک انتخاب عالی برای اعتبارسنجی داده های فرم تبدیل می کند.

از سوی دیگر، React-Hook-Form یک کتابخانه فرم سبک وزن برای React است که اجزای کنترل نشده را در بر می گیرد و با API مبتنی بر قلاب بصری خود، فرم سازی را ساده می کند.

در این آموزش، نحوه ساخت فرم ایمن نوع با استفاده از React-Hook-Form برای مدیریت فرم و Zod برای اعتبارسنجی سمت کلاینت و سمت سرور را یاد خواهید گرفت.

در اینجا چیزی است که ما پوشش خواهیم داد:

    شروع شدن

    نحوه تعریف انواع فرم

    نحوه ایجاد فرم با react-hook-form

    نحوه ادغام Zod برای اعتبار سنجی طرحواره

    نحوه رسیدگی به خطاهای سمت سرور

    نتیجه

شروع شدن

برای شروع، دیگ شروع کننده پروژه را شبیه سازی کنید. ترمینال خود را باز کنید و این دستور را اجرا کنید:

 git clone --branch starter https://github.com/Giftea/zod-rhf-fcc.git

می توانید نسخه نهایی را در GitHub از اینجا بیابید.

هنگامی که دیگ بخار را روی دستگاه محلی خود گرفتید، دستورات زیر را برای نصب وابستگی ها و شروع پروژه اجرا کنید:

 npm install npm run dev

مرورگر خود را به http://localhost:3000 هدایت کنید و صفحه شروع پروژه ما به شما خوش آمد می گوید.

اسکرین شات-2024-01-16-at-15.21.10
میزبان محلی

نحوه تعریف انواع فرم

فایل /types.ts شامل انواع و طرحواره های مربوط به فیلدهای فرم ما و اعتبارسنجی آنها خواهد بود. فایل /types.ts را با کد زیر به روز کنید:

 import { FieldError, UseFormRegister } from "react-hook-form"; export type FormData = { email: string; githubUrl: string; yearsOfExperience: number; password: string; confirmPassword: string; }; export type FormFieldProps = { type: string; placeholder: string; name: ValidFieldNames; register: UseFormRegister<FormData>; error: FieldError | undefined; valueAsNumber?: boolean; }; export type ValidFieldNames = | "email" | "githubUrl" | "yearsOfExperience" | "password" | "confirmPassword";
/types.ts

FormData ساختار داده های مورد انتظار در فرم را نشان می دهد.

FormFieldProps ویژگی های مورد انتظار مولفه فیلد فرم را تعریف می کند (که بعداً خواهیم ساخت). آن شامل:

type : نوع فیلد ورودی (به عنوان مثال، متن، رمز عبور).

placeholder : متن جای جای برای فیلد ورودی.

name : نام فیلد که با یکی از نام فیلدهای معتبر تعریف شده در نوع ValidFieldNames مطابقت دارد.

register : تابعی از react-hook-form ( UseFormRegister<FormData> ) که برای ثبت فیلد ورودی با فرم استفاده می شود.

error : هر گونه خطای اعتبارسنجی مرتبط با فیلد را نشان می دهد. اگر خطایی وجود نداشته باشد، می توان آن را undefined .

valueAsNumber (اختیاری): یک پرچم بولی که نشان می دهد آیا مقدار فیلد باید به عنوان یک عدد در نظر گرفته شود یا خیر. پیش‌فرض به undefined .

ValidFieldNames یک نوع اتحادیه است که نام فیلدهای معتبر فرم را بر می شمارد. اینها با فیلدهای تعریف شده در نوع FormData مطابقت دارند.

نحوه ایجاد فرم با React-Hook-Form

اکنون که انواع فرم را تعریف کردیم، اجازه دهید یک جزء فیلد فرم قابل استفاده مجدد و مولفه فرم ایجاد کنیم.

یک مؤلفه فیلد فرم قابل استفاده مجدد ایجاد کنید

بیایید یک مؤلفه FormField قابل استفاده مجدد ایجاد کنیم که رندر یک عنصر ورودی، ثبت آن با فرم را با استفاده از react-hook-form و نمایش پیام خطای اعتبارسنجی در صورت لزوم انجام می دهد.

به فایل /app/components/FormField.tsx بروید و مؤلفه را به روز کنید:

 import { FormFieldProps } from "@/types"; const FormField: React.FC<FormFieldProps> = ({ type, placeholder, name, register, error, valueAsNumber, }) => ( <> <input type={type} placeholder={placeholder} {...register(name, { valueAsNumber })} /> {error && <span className="error-message">{error.message}</span>} </> ); export default FormField;
/app/components/FormField.tsx

واردات:

کامپوننت نوع FormFieldProps را از ماژول @/types وارد می کند. این نوع شامل ویژگی های مورد انتظار برای یک فیلد فرم است، مانند type ، placeholder ، name ، register ، error ، و valueAsNumber .

عنصر ورودی:

کامپوننت یک عنصر <input> را با صفات تنظیم شده بر اساس ویژگی های ارائه شده ( type ، placeholder ، name ) ارائه می کند.

دستور ...register(name, { valueAsNumber }) برای ثبت فیلد ورودی با فرم استفاده می شود و مدیریت حالت فرم را فعال می کند.

رسیدگی به خطا:

اگر یک خطای اعتبارسنجی وجود داشته باشد، یک عنصر <span> ارائه می شود و پیام خطا را نمایش می دهد.

کامپوننت فرم را ایجاد کنید

مؤلفه Form از کتابخانه react-hook-form برای مدیریت حالت فرم استفاده می کند. فیلدهای فرم را با استفاده از مولفه قابل استفاده مجدد FormField ما مدولار می کند.

به app/components/Form.tsx بروید و آن را با کد زیر به روز کنید:

 import { useForm } from "react-hook-form"; import { FormData } from "@/types"; import FormField from "./FormField"; function Form() { const { register, handleSubmit, formState: { errors }, setError, } = useForm<FormData>(); const onSubmit = async (data: FormData) => { console.log("SUCCESS", data); } return ( <form onSubmit={handleSubmit(onSubmit)}> <div className="grid col-auto"> <h1 className="text-3xl font-bold mb-4"> Zod & React-Hook-Form </h1> <FormField type="email" placeholder="Email" name="email" register={register} error={errors.email} /> <FormField type="text" placeholder="GitHub URL" name="githubUrl" register={register} error={errors.githubUrl} /> <FormField type="number" placeholder="Years of Experience (1 - 10)" name="yearsOfExperience" register={register} error={errors.yearsOfExperience} valueAsNumber /> <FormField type="password" placeholder="Password" name="password" register={register} error={errors.password} /> <FormField type="password" placeholder="Confirm Password" name="confirmPassword" register={register} error={errors.confirmPassword} /> <button type="submit" className="submit-button"> Submit </button> </div> </form> ); } export default Form;
/app/components/Form.tsx

واردات:

قلاب useForm عملکردی را برای مدیریت وضعیت فرم و اعتبار سنجی ارائه می دهد.

FormData ساختار داده های فرم را نشان می دهد.

FormField جزء فیلد فرم قابل استفاده مجدد ما است.

جزء فرم:

توابع مربوط به فرم و متغیرهای حالت از قلاب useForm که به صراحت با FormData تایپ می شود تا شکل داده های فرم را تعریف کند، تخریب می شوند.

در فرم، اجزای FormField برای فیلدهای ورودی مختلف مانند ایمیل، URL GitHub، سال‌ها تجربه، رمز عبور و رمز عبور تأیید ارائه می‌شوند.

کد اجرا:

کامپوننت Form را در فایل /app/page.tsx وارد کنید:

 "use client"; import Form from "./components/Form"; function Home() { return ( <main className="flex min-h-screen flex-col items-center justify-between p-24"> <Form /> </main> ); } export default Home;
/app/page.tsx

برای مشاهده فرم به http://localhost:3000/ مراجعه کنید:

اسکرین شات-2024-01-11-at-11.40.22
http://localhost:3000/

به طور خلاصه، مؤلفه Form ما یک ساختار فرم اولیه است که از کتابخانه react-hook-form برای مدیریت حالت استفاده می‌کند و از یک مؤلفه FormField قابل استفاده مجدد برای مدیریت رندر و تأیید فیلدهای فرم جداگانه استفاده می‌کند.

نحوه ادغام Zod برای اعتبار سنجی طرحواره

Zod به عنوان یک کتابخانه اعلان طرح و اعتبار، با TypeScript به عنوان تمرکز اصلی آن برجسته است. اصطلاح «طرحواره» انواع داده‌های مختلفی را در بر می‌گیرد، از رشته‌ها، اعداد و بولی تا اشیاء پیچیده‌تر.

با Zod یک طرحواره فرم تعریف کنید

بیایید با استفاده از Zod برای ساختار فرم خود، یک طرح فرم با پشتوانه TypeScript ایجاد کنیم.

به فایل /types.ts خود بروید، واردات جدید را اضافه کنید و یک طرح کاربری با کد زیر ایجاد کنید:

 import { z, ZodType } from "zod"; // Add new import export const UserSchema: ZodType<FormData> = z .object({ email: z.string().email(), githubUrl: z .string() .url() .includes("github.com", { message: "Invalid GitHub URL" }), yearsOfExperience: z .number({ required_error: "required field", invalid_type_error: "Years of Experience is required", }) .min(1) .max(10), password: z .string() .min(8, { message: "Password is too short" }) .max(20, { message: "Password is too long" }), confirmPassword: z.string(), }) .refine((data) => data.password === data.confirmPassword, { message: "Passwords do not match", path: ["confirmPassword"], // path of error });
/types.ts

واردات:

z نمونه ای از شی Zod است.

ZodType یک نوع عمومی است که یک نوع طرحواره Zod را برای یک ساختار داده خاص نشان می دهد.

طرحواره کاربر:

export const UserSchema: ZodType<FormData> = ... : UserSchema یک نوع Zod را نشان می دهد که با ساختار تعریف شده توسط نوع FormData مطابقت دارد.

z.object({...}) : این قسمت با استفاده از Zod یک طرحواره شی را تعریف می کند. شی دارای چندین فیلد است که هر کدام قوانین اعتبار سنجی خاص خود را دارند.

در داخل شی، هر فیلد با قوانین اعتبارسنجی خاص خود با استفاده از متدهای Zod مانند z.string() , z.url() ، z.number() و z.min() تعریف می شود. پیام های خطای سفارشی اختیاری برای برخی از فیلدها ارائه شده است.

z.refine((data) => data.password === data.confirmPassword, { /* ... */ }); : اصلاحاتی را به طرح اضافه می کند تا تحلیل کند که آیا فیلدهای password و confirmPassword مطابقت دارند یا خیر. در غیر این صورت، یک پیغام خطای سفارشی ارائه می شود و خطا با قسمت confirmPassword مرتبط می شود.

نحوه ادغام Zod با React-Hook-Form برای اعتبارسنجی

اکنون که طرح Zod را برای فرم تنظیم کردیم، بیایید آن را با مؤلفه Form موجود خود ادغام کنیم. برای این کار از zodResolver از کتابخانه @hookform استفاده می کنیم.

zodResolver یک تابع حل کننده است که اعتبار سنجی طرحواره Zod را با فرآیند اعتبار سنجی فرم یکپارچه می کند.

به فایل app/components/Form.tsx بروید و آن را با کد زیر به روز کنید:

 // Update imports import { FormData, UserSchema } from "@/types"; import { zodResolver } from "@hookform/resolvers/zod"; function Form() { const { register, handleSubmit, formState: { errors }, setError, } = useForm<FormData>({ resolver: zodResolver(UserSchema), // Apply the zodResolver }); {/* Existing Code...*/} }
/app/components/Form.tsx

اگر سعی کنید فرم را با فیلدهای ورودی خالی ارسال کنید، پیام های خطا را در مرورگر خواهید دید.

اسکرین شات-2024-01-11-at-20.38.03
پیام های خطا - http://localhost:3000/

علاوه بر این، پیام‌های خطای سفارشی ما، مانند درخواست از کاربران برای ارائه یک URL معتبر GitHub و تحلیل مطابقت گذرواژه‌ها، در تصویر زیر نشان داده شده‌اند:

اسکرین شات-2024-01-11-at-20.59.18
پیام های خطای سفارشی - http://localhost:3000/

نحوه رسیدگی به خطاهای سمت سرور

هنگام ایجاد فرم ها، یکپارچگی داده ها و ایمنی نوع بسیار مهم است، از آنجایی که داده های ارسالی به سرور وب سایت می رود. این ما را به اهمیت رسیدگی به خطاهای سمت سرور هدایت می کند - یک اقدام امنیتی اضافی برای اطمینان از دقیق و غیر مخرب بودن داده های مشتری.

نحوه پیاده سازی اعتبارسنجی سمت سرور

برای پیاده سازی اعتبار سنجی سمت سرور، از قابلیت های Backend Next.js برای ساخت یک سرور ساده استفاده می کنیم. این سرور داده های ارسال شده از طریق فرم ما را دریافت و تأیید می کند.

به app/api/form/route.ts بروید و کد زیر را وارد کنید:

 import { UserSchema } from "@/types"; import { NextResponse } from "next/server"; export async function POST(request: Request) { // Retrieve the JSON data from the request body const body = await request.json(); // Use Zod to validate the received data against the UserSchema const result = UserSchema.safeParse(body); // Check if the validation is successful if (result.success) { return NextResponse.json({ success: true }); } // If validation errors, map them into an object const serverErrors = Object.fromEntries( result.error?.issues?.map((issue) => [issue.path[0], issue.message]) || [] ); // Respond with a JSON object containing the validation errors return NextResponse.json({ errors: serverErrors }); }
/app/api/form/route.ts

واردات:

UserSchema که قبلا تعریف کردیم وارد شده است.

NextResponse از ماژول next/server که به ما امکان می دهد پاسخ های سرور را در محیط Next.js ایجاد کنیم.

تابع POST:

const body = await request.json() : داده های JSON را از بدنه درخواست بازیابی می کند و در متغیر body ذخیره می کند.

const result = UserSchema.safeParse(body) : از روش safeParse ارائه شده توسط Zod برای اعتبارسنجی داده های دریافتی در برابر UserSchema استفاده می کند. نتیجه شامل اطلاعاتی درباره موفقیت آمیز بودن اعتبارسنجی و در غیر این صورت، جزئیات مربوط به مسائل اعتبار سنجی است.

if (result.success) { return NextResponse.json({ success: true }); } : اگر اعتبارسنجی موفقیت آمیز باشد، یک پاسخ JSON با { success: true } ارسال می شود.

const serverErrors = Object.fromEntries(/* ... */) : اگر خطاهای اعتبارسنجی وجود داشته باشد، کد آنها را در یک شی با نام فیلدها و پیام های خطای مربوطه ترسیم می کند.

return NextResponse.json({ errors: serverErrors }) : با یک شی JSON حاوی خطاهای اعتبار سنجی پاسخ می دهد.

در ترمینال خود، اجرای پروژه را متوقف کنید و دوباره npm run dev برای راه اندازی مجدد سرور اجرا کنید.

نحوه ادغام اعتبارسنجی سمت سرور

برای ادغام اعتبار سنجی سمت سرور، باید تابع onSubmit را در مؤلفه Form به روز کنیم.

به فایل /app/components/Form.tsx بروید و تابع import و onSubmit به‌روزرسانی کنید:

 // Update import import { FormData, UserSchema, ValidFieldNames } from "@/types"; import axios from "axios"; function Form() { {/* Existing Code... */} const onSubmit = async (data: FormData) => { try { const response = await axios.post("/api/form", data); // Make a POST request const { errors = {} } = response.data; // Destructure the 'errors' property from the response data // Define a mapping between server-side field names and their corresponding client-side names const fieldErrorMapping: Record<string, ValidFieldNames> = { email: "email", githubUrl: "githubUrl", yearsOfExperience: "yearsOfExperience", password: "password", confirmPassword: "confirmPassword", }; // Find the first field with an error in the response data const fieldWithError = Object.keys(fieldErrorMapping).find( (field) => errors[field] ); // If a field with an error is found, update the form error state using setError if (fieldWithError) { // Use the ValidFieldNames type to ensure the correct field names setError(fieldErrorMapping[fieldWithError], { type: "server", message: errors[fieldWithError], }); } } catch (error) { alert("Submitting form failed!"); } }; {/* Existing Code... */} }
/app/components/Form.tsx

axios برای ایجاد یک درخواست POST به نقطه پایانی سرور /api/form با داده های فرم استفاده می شود.

شی errors از داده های پاسخ استخراج می شود.

یک نگاشت ( fieldErrorMapping ) بین نام فیلدها و ValidFieldNames مربوط به آنها تعریف شده است.

سپس با تکرار روی فیلد fieldErrorMapping و یافتن اولین فیلد دارای خطا، تحلیل می‌کند که آیا خطاهای مربوط به فیلدهای فرم وجود دارد یا خیر.

اگر فیلدی با خطا پیدا شد، تابع setError از react-hook-form برای تنظیم خطا برای فیلد مربوطه استفاده می شود. نوع خطا به عنوان "سرور" علامت گذاری شده است و پیام خطا از پاسخ سرور می آید.

اگر خطایی در کل بلوک try وجود داشته باشد، خطا را دریافت می کند و هشداری را نشان می دهد: "ارسال فرم انجام نشد!"

اکنون، برای آزمایش اینکه آیا می‌توانیم خطاهایی را از سرور دریافت کنیم، عمداً داده‌های فرمت‌شده نامناسب را به سرور ارسال می‌کنیم. در تابع onSubmit خود، شی data را با داده های نادرست در بلوک کد زیر جایگزین کنید:

 {/* Existing Code...*/} const onSubmit = async (data: FormData) => { try { // Update data sent in axios with incorrect data const response = await axios.post("/api/form", { email: "Not an email", githubUrl: "Not a URL", yearsOfExperience: "Hello", password: 1234, confirmPassword: 1234, }); // Make a POST request {/* Existing Code...*/} }
/app/components/Form.tsx

فرم را در مرورگر به طور معمول پر کنید و فرم را ارسال کنید.

تب "شبکه" را در ابزارهای توسعه دهنده مرورگر تحلیل کنید. همانطور که در تصویر زیر نشان داده شده است، پیام های خطایی را خواهید دید که مستقیماً از سرور ارسال می شود:

اسکرین شات-2024-01-12-at-10.21.47
خطاهای سرور - http://localhost:3000/

اگر هیچ پاسخی از سرور خود دریافت نکردید، به یاد داشته باشید که اجرای پروژه خود را در ترمینال خود متوقف کنید و دوباره npm run dev برای راه اندازی مجدد سرور اجرا کنید.

نتیجه

در این آموزش یک فرم با React-Hook-Form ساختیم و با Zod اعتبارسنجی کردیم. با Zod، اعتبار سنجی طرحواره، پیام های خطای سفارشی شده و خطاهای سمت سرور را تحلیل کردیم. ادغام React-Hook-Form و Zod یک راه حل قدرتمند و سازگار با توسعه دهندگان برای ایجاد فرم های انعطاف پذیر ارائه می دهد.

اگر سوالی دارید می توانید در توییتر با من تماس بگیرید.

می توانید کد منبع و برنامه مستقر شده را تحلیل کنید.

منابع:

مستندات زود

رسیدگی به خطای زود

React-Hook-Form Documentation

حل کننده های Hookform

خبرکاو

ارسال نظر




تبليغات ايهنا تبليغات ايهنا

تمامی حقوق مادی و معنوی این سایت متعلق به خبرکاو است و استفاده از مطالب با ذکر منبع بلامانع است