كيفية إنشاء نماذج باستخدام مسارات API
تتيح لك النماذج إنشاء وتحديث البيانات في تطبيقات الويب. يوفر Next.js طريقة قوية للتعامل مع تحوير البيانات باستخدام مسارات API. سيرشدك هذا الدليل حول كيفية معالجة إرسال النماذج على الخادم.
النماذج على الخادم
لمعالجة إرسال النماذج على الخادم، قم بإنشاء نقطة نهاية API لتعديل البيانات بشكل آمن.
import type { NextApiRequest, NextApiResponse } from 'next'
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
const data = req.body
const id = await createItem(data)
res.status(200).json({ id })
}
export default function handler(req, res) {
const data = req.body
// استدعاء قاعدة البيانات، إلخ.
// const id = await createItem(data)
// ...
res.status(200).json({ data })
}
ثم استدع مسار API من العميل باستخدام معالج الأحداث:
import { FormEvent } from 'react'
export default function Page() {
async function onSubmit(event: FormEvent<HTMLFormElement>) {
event.preventDefault()
const formData = new FormData(event.currentTarget)
const response = await fetch('/api/submit', {
method: 'POST',
body: formData,
})
// التعامل مع الاستجابة إذا لزم الأمر
const data = await response.json()
// ...
}
return (
<form onSubmit={onSubmit}>
<input type="text" name="name" />
<button type="submit">Submit</button>
</form>
)
}
export default function Page() {
async function onSubmit(event) {
event.preventDefault()
const formData = new FormData(event.target)
const response = await fetch('/api/submit', {
method: 'POST',
body: formData,
})
// التعامل مع الاستجابة إذا لزم الأمر
const data = await response.json()
// ...
}
return (
<form onSubmit={onSubmit}>
<input type="text" name="name" />
<button type="submit">Submit</button>
</form>
)
}
معلومة مفيدة:
- لا تحدد مسارات API رؤوس CORS، مما يعني أنها تعمل فقط من نفس المصدر افتراضيًا.
- نظرًا لأن مسارات API تعمل على الخادم، يمكننا استخدام قيم حساسة (مثل مفاتيح API) من خلال متغيرات البيئة دون الكشف عنها للعميل. وهذا أمر حاسم لأمان تطبيقك.
التحقق من صحة النموذج
نوصي باستخدام التحقق من صحة HTML مثل required
و type="email"
للتحقق الأساسي من صحة النموذج على جانب العميل.
للتحقق المتقدم من صحة النموذج على جانب الخادم، يمكنك استخدام مكتبة تحقق من المخططات مثل zod للتحقق من حقول النموذج قبل تعديل البيانات:
import type { NextApiRequest, NextApiResponse } from 'next'
import { z } from 'zod'
const schema = z.object({
// ...
})
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
const parsed = schema.parse(req.body)
// ...
}
import { z } from 'zod'
const schema = z.object({
// ...
})
export default async function handler(req, res) {
const parsed = schema.parse(req.body)
// ...
}
معالجة الأخطاء
يمكنك استخدام حالة React لعرض رسالة خطأ عند فشل إرسال النموذج:
import React, { useState, FormEvent } from 'react'
export default function Page() {
const [isLoading, setIsLoading] = useState<boolean>(false)
const [error, setError] = useState<string | null>(null)
async function onSubmit(event: FormEvent<HTMLFormElement>) {
event.preventDefault()
setIsLoading(true)
setError(null) // مسح الأخطاء السابقة عند بدء طلب جديد
try {
const formData = new FormData(event.currentTarget)
const response = await fetch('/api/submit', {
method: 'POST',
body: formData,
})
if (!response.ok) {
throw new Error('Failed to submit the data. Please try again.')
}
// التعامل مع الاستجابة إذا لزم الأمر
const data = await response.json()
// ...
} catch (error) {
// التقاط رسالة الخطأ لعرضها للمستخدم
setError(error.message)
console.error(error)
} finally {
setIsLoading(false)
}
}
return (
<div>
{error && <div style={{ color: 'red' }}>{error}</div>}
<form onSubmit={onSubmit}>
<input type="text" name="name" />
<button type="submit" disabled={isLoading}>
{isLoading ? 'جاري التحميل...' : 'إرسال'}
</button>
</form>
</div>
)
}
import React, { useState } from 'react'
export default function Page() {
const [isLoading, setIsLoading] = useState(false)
const [error, setError] = useState(null)
async function onSubmit(event) {
event.preventDefault()
setIsLoading(true)
setError(null) // مسح الأخطاء السابقة عند بدء طلب جديد
try {
const formData = new FormData(event.currentTarget)
const response = await fetch('/api/submit', {
method: 'POST',
body: formData,
})
if (!response.ok) {
throw new Error('Failed to submit the data. Please try again.')
}
// التعامل مع الاستجابة إذا لزم الأمر
const data = await response.json()
// ...
} catch (error) {
// التقاط رسالة الخطأ لعرضها للمستخدم
setError(error.message)
console.error(error)
} finally {
setIsLoading(false)
}
}
return (
<div>
{error && <div style={{ color: 'red' }}>{error}</div>}
<form onSubmit={onSubmit}>
<input type="text" name="name" />
<button type="submit" disabled={isLoading}>
{isLoading ? 'جاري التحميل...' : 'إرسال'}
</button>
</form>
</div>
)
}
عرض حالة التحميل
يمكنك استخدام حالة React لعرض حالة التحميل عند إرسال النموذج على الخادم:
import React, { useState, FormEvent } from 'react'
export default function Page() {
const [isLoading, setIsLoading] = useState<boolean>(false)
async function onSubmit(event: FormEvent<HTMLFormElement>) {
event.preventDefault()
setIsLoading(true) // تعيين التحميل إلى true عند بدء الطلب
try {
const formData = new FormData(event.currentTarget)
const response = await fetch('/api/submit', {
method: 'POST',
body: formData,
})
// التعامل مع الاستجابة إذا لزم الأمر
const data = await response.json()
// ...
} catch (error) {
// التعامل مع الخطأ إذا لزم الأمر
console.error(error)
} finally {
setIsLoading(false) // تعيين التحميل إلى false عند اكتمال الطلب
}
}
return (
<form onSubmit={onSubmit}>
<input type="text" name="name" />
<button type="submit" disabled={isLoading}>
{isLoading ? 'جاري التحميل...' : 'إرسال'}
</button>
</form>
)
}
import React, { useState } from 'react'
export default function Page() {
const [isLoading, setIsLoading] = useState(false)
async function onSubmit(event) {
event.preventDefault()
setIsLoading(true) // تعيين التحميل إلى true عند بدء الطلب
try {
const formData = new FormData(event.currentTarget)
const response = await fetch('/api/submit', {
method: 'POST',
body: formData,
})
// التعامل مع الاستجابة إذا لزم الأمر
const data = await response.json()
// ...
} catch (error) {
// التعامل مع الخطأ إذا لزم الأمر
console.error(error)
} finally {
setIsLoading(false) // تعيين التحميل إلى false عند اكتمال الطلب
}
}
return (
<form onSubmit={onSubmit}>
<input type="text" name="name" />
<button type="submit" disabled={isLoading}>
{isLoading ? 'جاري التحميل...' : 'إرسال'}
</button>
</form>
)
}
إعادة التوجيه
إذا كنت ترغب في توجيه المستخدم إلى مسار مختلف بعد التحوير، يمكنك استخدام redirect
إلى أي عنوان URL مطلق أو نسبي:
import type { NextApiRequest, NextApiResponse } from 'next'
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
const id = await addPost()
res.redirect(307, `/post/${id}`)
}
export default async function handler(req, res) {
const id = await addPost()
res.redirect(307, `/post/${id}`)
}