نکات ضروری برای طراحی فرم در Next.js
ﺯﻣﺎﻥ ﻣﻄﺎﻟﻌﻪ: 6 دقیقه

نکات ضروری برای طراحی فرم در Next.js

فرم‌ها یکی از حیاتی‌ترین اجزای هر اپلیکیشن وب هستند؛ چه برای ثبت‌نام کاربران، چه برای ورود، جست‌وجو، ارسال بازخورد یا ثبت سفارش. در فریم‌ورک Next.js که ترکیبی از قابلیت‌های React و SSR (رندر سمت سرور) را ارائه می‌دهد، طراحی فرم نه‌تنها به‌لحاظ ظاهری بلکه از نظر تجربه کاربری (UX)، اعتبارسنجی داده‌ها و امنیت، نیازمند توجهی ویژه است.

در این مقاله، به بررسی نکات ضروری طراحی فرم در Next.js می‌پردازیم، سپس اعتبارسنجی فرم در Next.js را هم در سمت کلاینت و هم در سمت سرور بررسی می‌کنیم. در ادامه با معرفی کتابخانه‌های رایج فرم در React مثل React Hook Form و Formik و ابزارهای اعتبارسنجی مانند Yup و Zod، گام‌به‌گام تا بهترین شیوه‌های ارسال و مدیریت فرم پیش می‌رویم.

ساختار پایه‌ی فرم در Next.js با استفاده از React Hook Form و Formik

برای مدیریت فرم‌ها در React/Next.js، استفاده از کتابخانه‌هایی مانند React Hook Form و Formik بسیار رایج است. این کتابخانه‌ها علاوه‌بر کاهش پیچیدگی کد، امکاناتی مثل کنترل وضعیت فیلدها، اعتبارسنجی هم‌زمان، نمایش خطاها، و بهینه‌سازی عملکرد را در اختیار توسعه‌دهنده قرار می‌دهند.

React Hook Form با Next.js

React Hook Form با استفاده از hookها، عملکردی سبک و بهینه ارائه می‌دهد. برای شروع:

npm install react-hook-form

مثالی از یک فرم ساده:

import { useForm } from "react-hook-form";

export default function ContactForm() {
  const { register, handleSubmit, formState: { errors } } = useForm();

  const onSubmit = data => {
    console.log(data);
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input {...register("name", { required: true })} placeholder="Name" />
      {errors.name && <span>نام الزامی است</span>}

      <input type="email" {...register("email", { required: true })} placeholder="Email" />
      {errors.email && <span>ایمیل الزامی است</span>}

      <button type="submit">ارسال</button>
    </form>
  );
}

Formik با Next.js

Formik یک کتابخانه قدیمی‌تر و پایدار برای فرم‌هاست که از state داخلی استفاده می‌کند:

npm install formik

نمونه فرم:

import { Formik, Form, Field, ErrorMessage } from 'formik';

export default function SimpleForm() {
  return (
    <Formik
      initialValues={{ name: '', email: '' }}
      validate={values => {
        const errors = {};
        if (!values.name) errors.name = 'نام الزامی است';
        if (!values.email) errors.email = 'ایمیل الزامی است';
        return errors;
      }}
      onSubmit={(values) => {
        console.log(values);
      }}
    >
      <Form>
        <Field name="name" placeholder="Name" />
        <ErrorMessage name="name" component="div" />

        <Field name="email" type="email" placeholder="Email" />
        <ErrorMessage name="email" component="div" />

        <button type="submit">ارسال</button>
      </Form>
    </Formik>
  );
}

مقایسه کلی

ویژگی React Hook Form Formik
حجم نهایی سبک‌تر سنگین‌تر
مدل مدیریت state با hook با state داخلی
عملکرد بهینه‌تر کندتر در فرم‌های بزرگ
یادگیری آسان ساده و قابل درک

 

اعتبارسنجی فرم در Next.js با Yup و Zod (سمت کلاینت)

اعتبارسنجی (validation) در سمت کلاینت یکی از مهم‌ترین مراحل طراحی فرم است؛ نه فقط برای بهبود تجربه کاربری (UX)، بلکه برای کاهش خطاهای سمت سرور و جلوگیری از ارسال داده‌های نامعتبر.

کتابخانه‌های محبوبی که معمولاً با React Hook Form یا Formik استفاده می‌شوند، شامل Yup و Zod هستند. هر دو امکان تعریف طرح (schema) برای داده‌ها را فراهم می‌کنند.

استفاده از Yup برای اعتبارسنجی فرم

Yup به‌صورت گسترده همراه با Formik یا React Hook Form استفاده می‌شود.

npm install yup @hookform/resolvers

نمونه استفاده با React Hook Form:

import { useForm } from "react-hook-form";
import { yupResolver } from "@hookform/resolvers/yup";
import * as yup from "yup";

const schema = yup.object({
  name: yup.string().required("نام الزامی است"),
  email: yup.string().email("فرمت ایمیل نادرست است").required("ایمیل الزامی است")
});

export default function ValidatedForm() {
  const { register, handleSubmit, formState: { errors } } = useForm({
    resolver: yupResolver(schema),
  });

  const onSubmit = data => console.log(data);

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input {...register("name")} placeholder="Name" />
      {errors.name && <span>{errors.name.message}</span>}

      <input {...register("email")} placeholder="Email" />
      {errors.email && <span>{errors.email.message}</span>}

      <button type="submit">ارسال</button>
    </form>
  );
}

استفاده از Zod برای اعتبارسنجی فرم

Zod در سال‌های اخیر محبوبیت زیادی یافته به‌دلیل یکپارچگی بهتر با TypeScript و طراحی مدرن‌تر.

npm install zod @hookform/resolvers

مثال با React Hook Form:

import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";

const schema = z.object({
  name: z.string().min(1, "نام الزامی است"),
  email: z.string().email("ایمیل معتبر نیست"),
});

export default function ZodForm() {
  const { register, handleSubmit, formState: { errors } } = useForm({
    resolver: zodResolver(schema),
  });

  const onSubmit = data => console.log(data);

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input {...register("name")} placeholder="Name" />
      {errors.name && <span>{errors.name.message}</span>}

      <input {...register("email")} placeholder="Email" />
      {errors.email && <span>{errors.email.message}</span>}

      <button type="submit">ارسال</button>
    </form>
  );
}

اعتبارسنجی سمت سرور در Next.js با API Routes

اعتبارسنجی سمت کلاینت به‌تنهایی کافی نیست. کاربران می‌توانند اعتبارسنجی فرانت‌اند را دور بزنند، بنابراین هرگونه داده‌ای که از فرم دریافت می‌شود، باید در سمت سرور نیز مجدداً اعتبارسنجی شود. در Next.js این کار معمولاً در مسیرهای API انجام می‌شود.

استفاده از API Routes برای پردازش فرم‌ها

Next.js قابلیت ایجاد مسیرهای API را در فولدر pages/api/ فراهم می‌کند. برای مثال:

pages/api/contact.js
export default async function handler(req, res) {
  if (req.method !== 'POST') {
    return res.status(405).json({ message: 'Method Not Allowed' });
  }

  const { name, email } = req.body;

  if (!name || !email || !email.includes('@')) {
    return res.status(400).json({ message: 'داده نامعتبر است' });
  }

  // پردازش داده‌های معتبر
  return res.status(200).json({ message: 'پیام دریافت شد' });
}

اعتبارسنجی پیشرفته در سرور با Yup یا Zod

شما می‌توانید همان schema که در کلاینت تعریف کرده‌اید، در سمت سرور نیز استفاده کنید (در صورت اشتراک فایل بین کلاینت و سرور).

مثلاً با Zod:

import { z } from 'zod';

const schema = z.object({
  name: z.string().min(1),
  email: z.string().email(),
});

export default async function handler(req, res) {
  if (req.method !== 'POST') return res.status(405).end();

  const result = schema.safeParse(req.body);

  if (!result.success) {
    return res.status(400).json({
      errors: result.error.flatten().fieldErrors,
    });
  }

  // اگر داده معتبر باشد:
  const data = result.data;
  return res.status(200).json({ message: 'با موفقیت دریافت شد', data });
}

چرا اعتبارسنجی سمت سرور ضروری است؟

  • جلوگیری از تزریق داده‌ی ناسالم
  • مقابله با حملات XSS و CSRF
  • سازگاری با محدودیت‌های پایگاه داده
  • جلوگیری از بار اضافی در منطق برنامه

بهترین شیوه‌ها برای ارسال فرم در Next.js و مدیریت وضعیت و خطا

ارسال فرم در Next.js می‌تواند به دو روش انجام شود:
۱. ارسال مستقیم به API Route (رایج‌ترین)
۲. استفاده از توابع سرور (Server Actions در نسخه‌های جدید Next.js)

در این بخش، روی شیوه‌ی استاندارد یعنی ارسال به API Route تمرکز می‌کنیم و نکاتی را درباره‌ی مدیریت وضعیت و خطا ارائه می‌دهیم.

ارسال فرم با fetch

در سمت کلاینت، می‌توان با fetch داده‌ها را به API Route ارسال کرد:

const onSubmit = async (data) => {
  const res = await fetch('/api/contact', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(data),
  });

  const result = await res.json();

  if (!res.ok) {
    // نمایش خطا
    console.error(result.errors || result.message);
  } else {
    // موفقیت
    alert('فرم با موفقیت ارسال شد');
  }
};

مدیریت وضعیت ارسال (در حال ارسال، موفق، خطا)

برای بهبود تجربه کاربر، بهتر است وضعیت فرم را مدیریت کنیم:

const [isSubmitting, setIsSubmitting] = useState(false);
const [error, setError] = useState(null);
const [success, setSuccess] = useState(false);

const onSubmit = async (data) => {
  setIsSubmitting(true);
  setError(null);
  setSuccess(false);

  const res = await fetch('/api/contact', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(data),
  });

  const result = await res.json();

  setIsSubmitting(false);

  if (!res.ok) {
    setError(result.message || 'خطایی رخ داده است');
  } else {
    setSuccess(true);
  }
};

تجربه کاربری بهتر برای فرم‌ها

  • نمایش فوری خطاهای اعتبارسنجی
  • نمایش وضعیت بارگذاری
  • غیرفعال کردن دکمه‌ی ارسال هنگام ارسال
  • پاک‌سازی فرم پس از موفقیت
  • استفاده از پیام‌های مناسب برای کاربر (feedback)

امنیت فرم‌ها در Next.js: جلوگیری از حملات و محافظت از داده‌ها

یکی از حساس‌ترین بخش‌های طراحی فرم در Next.js، حفظ امنیت داده‌ها و مقابله با حملات رایج است. حتی اگر فرم از نظر ظاهری و کارکردی به‌خوبی طراحی شده باشد، عدم رعایت نکات امنیتی می‌تواند کل اپلیکیشن را در معرض آسیب قرار دهد.

در این بخش به نکات کلیدی امنیت فرم‌ها در Next.js می‌پردازیم.

۱. اعتبارسنجی سمت سرور را همیشه انجام دهید

کلاینت قابل اعتماد نیست. همیشه باید داده‌ها در سمت سرور نیز بررسی شوند تا از ورود داده‌ی مخرب جلوگیری شود.

۲. جلوگیری از XSS (Cross-Site Scripting)

اگر داده‌ی ورودی کاربر را بدون پالایش در HTML درج کنید، ممکن است کاربر مخرب اسکریپت دلخواه خود را اجرا کند.

مثال ناامن:

<div dangerouslySetInnerHTML={{ __html: userInput }} />

پیشنهاد: داده‌های ورودی را encode یا escape کنید یا اصلاً از dangerouslySetInnerHTML استفاده نکنید مگر با پالایش دقیق.

۳. محافظت در برابر CSRF (Cross-Site Request Forgery)

در فرم‌هایی که نیاز به احراز هویت دارند، استفاده از توکن CSRF الزامی است. در Next.js، می‌توان از کتابخانه‌هایی مثل next-auth یا csrf استفاده کرد تا توکن CSRF برای هر فرم صادر و بررسی شود.

۴. محدود کردن نرخ ارسال (Rate Limiting)

برای جلوگیری از ارسال اسپم یا حملات DoS، بهتر است نرخ درخواست‌ها محدود شود. می‌توان از ابزارهایی مانند: express-rate-limit و next-rate-limit استفاده کرد.

۵. استفاده از HTTPS در محیط تولید

اطمینان حاصل کنید که سایت در محیط production از HTTPS استفاده می‌کند تا داده‌های فرم رمزنگاری‌شده منتقل شوند.

۶. محافظت در برابر حملات تزریق (Injection)

در صورتی که داده‌های فرم به دیتابیس فرستاده می‌شوند، استفاده از ORMهایی مانند Prisma یا کوئری‌های آماده (Prepared Statements) به‌شدت توصیه می‌شود.

در پایان

فرم‌ها نقطه‌ی تماس اصلی کاربر با اپلیکیشن شما هستند. اگرچه ساختار اولیه‌ی یک فرم ممکن است ساده به نظر برسد، اما طراحی حرفه‌ای و ایمن آن در Next.js نیازمند درک دقیق از مباحثی همچون مدیریت وضعیت، اعتبارسنجی دوطرفه، امنیت، تجربه کاربری و ساختار معماری است.

در این مطلب آموختیم که:

React Hook Form و Formik دو ابزار قدرتمند برای مدیریت فرم در React/Next.js هستند؛ اولی سبک‌تر و مدرن‌تر، دومی ساده و قدیمی‌تر. اعتبارسنجی سمت کلاینت با استفاده از Yup یا Zod قابل انجام است، اما همیشه باید در سمت سرور نیز تکرار شود. API Routes در Next.js امکان پیاده‌سازی فرم‌های امن و ساختارمند را فراهم می‌کنند. تجربه کاربری (UX) فرم‌ها با مدیریت مناسب وضعیت، نمایش خطاها و جلوگیری از ارسال‌های ناخواسته، بهبود می‌یابد. امنیت فرم با اقداماتی مانند جلوگیری از XSS، استفاده از CSRF token، محدود کردن نرخ درخواست‌ها و اعتبارسنجی سرور تضمین می‌شود. طراحی فرم در Next.js، اگر به‌درستی انجام شود، نه‌تنها اعتماد کاربر را جلب می‌کند، بلکه امنیت، عملکرد و مقیاس‌پذیری اپلیکیشن را نیز ارتقا می‌دهد.

چه امتیازی برای این مقاله میدهید؟

خیلی بد
بد
متوسط
خوب
عالی
در انتظار ثبت رای

/@arastoo
ارسطو عباسی
کارشناس تولید و بهینه‌سازی محتوا

کارشناس ارشد تولید و بهینه‌سازی محتوا و تکنیکال رایتینگ - https://arastoo.net

دیدگاه و پرسش

برای ارسال دیدگاه لازم است وارد شده یا ثبت‌نام کنید ورود یا ثبت‌نام

در حال دریافت نظرات از سرور، لطفا منتظر بمانید

در حال دریافت نظرات از سرور، لطفا منتظر بمانید

ارسطو عباسی

کارشناس تولید و بهینه‌سازی محتوا

مقالات برگزیده

مقالات برگزیده را از این قسمت میتوانید ببینید

مشاهده همه مقالات