فرمها در وبسایتهای مدرن بسیار ضروری هستند، زیرا به ما کمک میکنند تا اطلاعات کاربران را جمعآوری کنیم. بنابراین، آگاهی از نحوه مدیریت صحیح فرمها هنگام ساخت برنامههای وب بسیار مهم میباشد. در این مقاله قصد داریم تا نحوه مدیریت فرم در Next.js با استفاده از Server Action و Zod را باهم بررسی کنیم.
منظور از Server Action چیست؟ Server Actionها دقیقاً همانطور که از اسمشان مشخص است، اکشنهایی هستند که بر روی سرور اجرا میشوند. با استفاده از Server Actionها، میتوانیم درخواستهایی به APIهای خارجی ارسال کنیم و یا این که دادههایی را از دیتابیس دریافت نماییم.
قبل از نسخه ۱۳ Next.js، برای مدیریت درخواستهای API و ارسال فرمها باید از routeها استفاده میکردیم، که این کار پیچیده و زمانبر بود. اما با معرفی Server Actionها، اکنون میتوانیم مستقیماً در کامپوننتهای Next.js خود با APIهای خارجی و دیتابیسها ارتباط برقرار کنیم.
با اجرای Server Actionها در سرور، پردازش دادهها بهصورت ایمن انجام میشود و خطرات امنیتی کاهش مییابد. Server Actionها همچنین در مدیریت فرمها مفید هستند. زیرا، این امکان را به ما میدهند که به طور مستقیم با سرور خود ارتباط برقرار کنیم و از این طریق دسترسی به اطلاعات حساس را برای کلاینت محدود نماییم.
دو روش برای ساخت Server Action وجود دارد:
"use server"
در سطح بالای یک تابع است. ما میتوانیم از این روش فقط در داخل یک سرور کامپوننت استفاده کنیم. استفاده از آن در یک کلاینت کامپوننت باعث بروز خطا خواهد میشود. به عنوان مثال:async function getPosts() { "use server"; // this makes getPosts a server actions // rest of code }
"use server"
را در بالای آن فایل قرار دهیم. این کار اطمینان میدهد که هر تابع async که از این فایل export میشود، یک Server Action به حساب میآید. به عنوان مثال:// action.ts "use server"; export async function getPosts() { const res = await fetch("https:..."); const data = res.json(); return data; }
در مثال کد بالا، getPosts
یک Server Action است.
Zod یک کتابخانه اعتبارسنجی است که میتوانیم از آن برای اعتبارسنجی ورودیهای فرم در سمت سرور استفاده کنیم. این کار اطمینان حاصل میکند که هم در سمت کلاینت و هم در سمت سرور یکپارچگی دادهها حفظ شود.
Zod یک کتابخانه مبتنی بر تایپاسکریپت است، به این معنی که بهطور پیشفرض با type safety همراه میباشد.
برای نصب کتابخانه Zod در برنامه Next.js خود، باید از دستور زیر استفاده کنیم:
npm install zod
در هسته کتابخانه Zod، اسکیماها قرار دارند. ما میتوانیم از schemaها برای اعتبارسنجی ورودیها استفاده کنیم. در ادامه نحوه تعریف یک schema را بررسی میکنیم:
import { z } from "zod"; const contactSchema = z.object({ name: z.string().min(2, { message: "Name must be at least 2 characters" }), email: z.string().email({ message: "Invalid email address" }), message: z .string() .min(10, { message: "Message must be at least 10 characters" }), });
در داخل contactSchema
مشخص میکنیم که:
name
از نوع string
است و باید حداقل ۲ کاراکتر داشته باشد،email
از نوع string
و email
است و باید یک ایمیل معتبر باشد،message
از نوع string
است و باید حداقل ۱۰ کاراکتر داشته باشد.ویژگی message
پیامی است که زمانی که همه یا هر یک از اعتبارسنجیها شکست بخورد، بر روی صفحه نمایش داده میشود.
در این بخش، ما رابط کاربری فرم تماس را میسازیم.
داخل دایرکتوری app
، یک پوشه به نام components
ایجاد میکنیم.سپس، داخل پوشه components
یک فایل جدید به نام contactForm.tsx
میسازیم و کد زیر را به آن اضافه میکنیم:
"use client"; function ContactForm() { return ( <form action=""> <input type="text" name="name" placeholder="Enter your name" /> <input type="email" name="email" placeholder="Enter your email" /> <textarea name="message" cols={30} rows={10} placeholder="Type in your message"></textarea> <button type="submit">Send Message</button> </form> ); } export default ContactForm;
در کد بالا، ما یک فرم تماس ساده ساختهایم و این فرم را به یک کلاینت کامپوننت تبدیل کردهایم؛ در ادامه دلیل این کار را بررسی خواهیم کرد.
کامپوننت ContactForm
را در فایل page.tsx
خود import میکنیم:
import ContactForm from "./components/contactForm.tsx"; function Home() { return ( <div> <h2>Contact Form</h2> <ContactForm /> </div> ); }
در این بخش از مقاله قصد داریم تا Server Actionها را ایجاد کرده و دادههای فرم را با استفاده از zod اعتبارسنجی کنیم.
در پوشه app
، یک پوشه دیگر به نام api
میسازیم. داخل پوشه api
، یک فایل به نام action.ts
ایجاد کرده و کد زیر را در آن قرار میدهیم:
"use server"; import { z } from "zod"; const contactFormSchema = z.object({ name: z.string().trim().min(1, { message: "Name field is required" }), email: z.string().email({ message: "Invalid email address" }), message: z.string().trim().min(1, { message: "Please type in a message" }), }); export async function sendEmail(prevState: any, formData: FormData) { const contactFormData = Object.fromEntries(formData); const validatedContactFormData = contactFormSchema.safeParse(contactFormData); if (!validatedContactFormData.success) { const formFieldErrors = validatedContactFormData.error.flatten().fieldErrors; return { errors: { name: formFieldErrors?.name, email: formFieldErrors?.email, message: formFieldErrors?.message, }, }; } return { success: "Your message was sent successfully!", }; }
در کد بالا، ما یک contactFormSchema
برای اعتبارسنجی ورودیهای فرم خود تعریف کردهایم.
تابع sendEmail
که Server Action ما است، دو آرگومان میپذیرد:
prevState
که برای نمایش پیامهای خطا و موفقیت استفاده میشود، وformData
که ورودیهای فرم ما هستند.FormData این امکان را فراهم میکند که تابع ما بدون نیاز به استفاده از هوک useState
به فیلدهای فرم دسترسی پیدا کند، و این کار بر اساس ویژگی name
انجام میشود.
ما از Object.fromEntries()
برای تبدیل دادههای خام formData
به یک آبجکت جاوااسکریپت معمولی استفاده میکنیم و آن را در متغیر contactFormData
ذخیره مینماییم.
سپس، دادههای contactFormData
را با استفاده از متد safeParse()
از اسکیما Zod، یعنی contactFormSchema
اعتبارسنجی میکنیم.
به عنوان یک تمرین خوب در برنامهنویسی، به صورت زود هنگام بررسی میکنیم که آیا اعتبارسنجی شکست خورده است یا خیر. اگر اعتبارسنجی شکست بخورد، یک آبجکت با ویژگی error
return میکنیم که شامل پیغام خطای هر فیلد فرم میباشد.
مقدار formFieldsError
به آبجکت error از Zod نسبت داده میشود، که پیغام خطای هر فیلد فرم را در بر میگیرد.
اگر همه چیز خوب پیش برود، تنها یک آبجکت error با ویژگی success
return میکنیم.
در این بخش، قصد داریم برای مدیریت فرم تماس، Server Action را به آن اضافه نماییم. به فایل contactForm.tsx
رفته و محتویات آن را با کدی که در این لینک قرار دارد، جایگزین میکنیم.
در این کدی که اکنون داریم، دو هوک useFormState
و useFormStatus
را از "react-dom"
و sendEmail
را از "api/action.ts".
import کردهایم.
سپس، یک متغیر initialState
ایجاد کردهایم تا state اولیه را نگه دارد. این متغیر در هوک useFormState
استفاده خواهد شد.
initialState
یک آبجکت است که شامل موارد زیر میباشد:
success
برای پیام موفقیت Server Action،errors
که برابر با آبجکت errors
است، که در صورت شکست اعتبارسنجی در return ،Server Action میکنیم.درون کامپوننت ContactForm
، از هوک useFormState
استفاده میکنیم. این هوک دو آرگومان میگیرد: Server Action و state اولیه؛ و یک آرایه با دو مقدار return میکند: state فعلی و formAction
.
formAction
به prop action
فرم پاس داده میشود. این امر مسئول ارسال فرم ما است که اعتبارسنجی Zod را شامل میشود.
زیر هر فیلد فرم، بهطور شرطی پیام خطای مربوط به هر فیلد نمایش داده میشود.
اگر فرم با موفقیت ارسال شده باشد، در قسمت انتهای فرم نیز پیام موفقیت نمایش داده میشود.
دکمه ارسال به یک کامپوننت جداگانه به نام SubmitButton
منتقل شده است تا بتوانیم از هوک useFormStatus
استفاده کنیم.
هوک useFormStatus
یک آبجکت return میکند که ویژگی pending
را شامل میشود. زمانی که فرم در حال ارسال است، ما میتوانیم از آن برای غیرفعال کردن دکمه ارسال استفاده کنیم.
از طریق این لینک میتوانیم به فایل کامل پروژه دسترسی داشته باشیم.
در این مقاله، با مفهوم Server Action آشنا شدیم و یاد گرفتیم چگونه باید از کتابخانه Zod استفاده کنیم. همچنین از Server Action و Zod برای ساخت و مدیریت یک فرم تماس استفاده کردیم. البته، Server Actionها فقط محدود به ارسال فرم نیستند و میتوانند برای دریافت دادهها از APIهای خارجی و دیتابیسها نیز مورد استفاده قرار بگیرند.
۵۰ درصد تخفیف ویژه زمستان فرانت کست تا ۱۴ دی
کد تخفیف: wnt