با استریم پاسخ اکشنهای سرور ریاکت برای پاسخهای فرم پیشرونده آشنا شوید. یاد بگیرید چگونه فرمهای سریعتر و واکنشگراتری برای تجربه کاربری بهتر بسازید.
استریم پاسخ اکشنهای سرور ریاکت: پاسخ فرم پیشرونده برای بهبود تجربه کاربری (UX)
اکشنهای سرور ریاکت (React Server Actions) یک تغییر پارادایم قدرتمند در نحوه مدیریت عملیات سمت سرور در برنامههای ریاکت ما ایجاد میکنند. یکی از هیجانانگیزترین ویژگیها، قابلیت استریم کردن تدریجی پاسخها است که به ما امکان میدهد بازخورد فوری به کاربران ارائه دهیم، حتی قبل از اینکه کل عملیات تکمیل شود. این ویژگی به خصوص برای فرمها مفید است، جایی که میتوانیم با بهروزرسانی رابط کاربری همزمان با در دسترس قرار گرفتن دادهها، تجربه کاربری واکنشگراتر و جذابتری ایجاد کنیم.
درک اکشنهای سرور ریاکت
اکشنهای سرور توابع ناهمگامی هستند که در سرور اجرا میشوند و از کامپوننتهای ریاکت آغاز میشوند. آنها چندین مزیت نسبت به فراخوانیهای API سنتی دارند:
- امنیت بهبود یافته: اکشنهای سرور مستقیماً روی سرور اجرا میشوند و خطر افشای دادهها یا منطق حساس به کلاینت را کاهش میدهند.
- کاهش کدهای تکراری (Boilerplate): آنها نیاز به مسیرهای API جداگانه و منطق واکشی داده در سمت کلاینت را از بین میبرند.
- عملکرد بهتر: آنها میتوانند از رندر سمت سرور (SSR) و کشینگ برای زمان بارگذاری اولیه سریعتر و عملکرد بهبود یافته استفاده کنند.
- ایمنی نوع (Type Safety): با TypeScript، اکشنهای سرور ایمنی نوع سرتاسری را فراهم میکنند و از سازگاری دادهها بین کلاینت و سرور اطمینان میدهند.
قدرت استریم پاسخ
ارسال فرمهای سنتی اغلب شامل ارسال تمام دادهها به سرور، انتظار برای پاسخ و سپس بهروزرسانی رابط کاربری است. این میتواند منجر به تأخیر محسوس شود، به خصوص برای فرمهای پیچیده یا اتصالات شبکه کند. استریم پاسخ به سرور اجازه میدهد تا دادهها را به صورت تکهتکه به کلاینت ارسال کند و ما را قادر میسازد تا رابط کاربری را به تدریج با در دسترس قرار گرفتن دادهها بهروز کنیم.
فرمی را تصور کنید که یک قیمت پیچیده را بر اساس ورودی کاربر محاسبه میکند. به جای انتظار برای تکمیل کل محاسبه، سرور میتواند نتایج میانی را به کلاینت استریم کند و بازخورد لحظهای به کاربر ارائه دهد. این میتواند تجربه کاربری را به طور قابل توجهی بهبود بخشد و باعث شود برنامه واکنشگراتر به نظر برسد.
پیادهسازی پاسخ فرم پیشرونده با اکشنهای سرور
بیایید یک مثال از نحوه پیادهسازی پاسخ فرم پیشرونده با اکشنهای سرور ریاکت را بررسی کنیم.
مثال: یک مبدل ارز لحظهای
ما یک فرم مبدل ارز ساده ایجاد میکنیم که بهروزرسانیهای لحظهای نرخ ارز را همزمان با تایپ کردن مقدار توسط کاربر ارائه میدهد.
۱. راهاندازی اکشن سرور
ابتدا، اکشن سروری را تعریف میکنیم که تبدیل ارز را انجام میدهد.
// server/actions.ts
'use server';
import { unstable_cache } from 'next/cache';
async function getExchangeRate(fromCurrency: string, toCurrency: string): Promise<number> {
// شبیهسازی دریافت نرخ ارز از یک API خارجی
console.log(`Fetching exchange rate for ${fromCurrency} to ${toCurrency}`);
await new Promise(resolve => setTimeout(resolve, 500)); // شبیهسازی تأخیر شبکه
if (fromCurrency === 'USD' && toCurrency === 'EUR') return 0.92;
if (fromCurrency === 'EUR' && toCurrency === 'USD') return 1.09;
if (fromCurrency === 'USD' && toCurrency === 'JPY') return 145;
if (fromCurrency === 'JPY' && toCurrency === 'USD') return 0.0069;
throw new Error(`Exchange rate not found for ${fromCurrency} to ${toCurrency}`);
}
export const convertCurrency = async (prevState: any, formData: FormData) => {
const fromCurrency = formData.get('fromCurrency') as string;
const toCurrency = formData.get('toCurrency') as string;
const amount = Number(formData.get('amount'));
try {
if (!fromCurrency || !toCurrency || isNaN(amount)) {
return { message: 'لطفا ورودی معتبر ارائه دهید.' };
}
// شبیهسازی استریم پاسخ
await new Promise(resolve => setTimeout(resolve, 250));
const exchangeRate = await unstable_cache(
async () => getExchangeRate(fromCurrency, toCurrency),
[`exchange-rate-${fromCurrency}-${toCurrency}`],
{ tags: [`exchange-rate-${fromCurrency}-${toCurrency}`] }
)();
await new Promise(resolve => setTimeout(resolve, 250));
const convertedAmount = amount * exchangeRate;
return { message: `مبلغ تبدیل شده: ${convertedAmount.toFixed(2)} ${toCurrency}` };
} catch (e: any) {
console.error(e);
return { message: 'تبدیل ارز با شکست مواجه شد.' };
}
};
در این مثال، اکشن سرور convertCurrency
نرخ ارز را (با تأخیر شبیهسازی شده) دریافت کرده و مبلغ تبدیل شده را محاسبه میکند. ما با استفاده از setTimeout
تأخیرهای مصنوعی برای شبیهسازی تأخیر شبکه و نمایش اثر استریم اضافه کردهایم.
۲. پیادهسازی کامپوننت ریاکت
سپس، کامپوننت ریاکتی را ایجاد میکنیم که از اکشن سرور استفاده میکند.
// app/page.tsx
'use client';
import { useState, useTransition } from 'react';
import { convertCurrency } from './server/actions';
import { useFormState } from 'react-dom';
export default function CurrencyConverter() {
const [fromCurrency, setFromCurrency] = useState('USD');
const [toCurrency, setToCurrency] = useState('EUR');
const [amount, setAmount] = useState('');
const [isPending, startTransition] = useTransition();
const [state, formAction] = useFormState(convertCurrency, { message: '' });
const handleSubmit = async (event: React.FormEvent) => {
event.preventDefault();
startTransition(() => {
formAction(new FormData(event.target as HTMLFormElement));
});
};
return (
<div>
<h2>مبدل ارز لحظهای</h2>
<form onSubmit={handleSubmit}>
<label htmlFor="fromCurrency">از:</label>
<select id="fromCurrency" name="fromCurrency" value={fromCurrency} onChange={(e) => setFromCurrency(e.target.value)}>
<option value="USD">USD</option>
<option value="EUR">EUR</option>
<option value="JPY">JPY</option>
</select>
<label htmlFor="toCurrency">به:</label>
<select id="toCurrency" name="toCurrency" value={toCurrency} onChange={(e) => setToCurrency(e.target.value)}>
<option value="EUR">EUR</option>
<option value="USD">USD</option>
<option value="JPY">JPY</option>
</select>
<label htmlFor="amount">مبلغ:</label>
<input
type="number"
id="amount"
name="amount"
value={amount}
onChange={(e) => setAmount(e.target.value)}
/>
<button type="submit" disabled={isPending}>
{isPending ? 'در حال تبدیل...' : 'تبدیل'}
</button>
</form>
<p>{state.message}</p>
</div>
);
}
نکات کلیدی:
- ما از هوک
useFormState
برای مدیریت وضعیت فرم و فراخوانی اکشن سرور استفاده میکنیم. - وضعیت
isPending
ازuseTransition
دکمه ارسال را غیرفعال کرده و پیام "در حال تبدیل..." را در حین اجرای اکشن نمایش میدهد و به کاربر بازخورد میدهد. - تابع
formAction
که توسطuseFormState
بازگردانده میشود، به طور خودکار ارسال فرم را مدیریت کرده و وضعیت را با پاسخ دریافتی از اکشن سرور بهروز میکند.
۳. درک بهروزرسانیهای پیشرونده
هنگامی که کاربر فرم را ارسال میکند، تابع handleSubmit
فراخوانی میشود. این تابع یک شیء FormData
از فرم ایجاد کرده و آن را به تابع formAction
ارسال میکند. سپس اکشن سرور روی سرور اجرا میشود. به دلیل تأخیرهای مصنوعی که در اکشن سرور ایجاد کردهایم، موارد زیر را مشاهده خواهید کرد:
- دکمه ارسال تقریباً بلافاصله به "در حال تبدیل..." تغییر میکند.
- پس از یک تأخیر کوتاه (۲۵۰ میلیثانیه)، کد دریافت نرخ ارز را شبیهسازی میکند.
- مبلغ تبدیل شده محاسبه شده و نتیجه به کلاینت بازگردانده میشود.
state.message
در کامپوننت ریاکت بهروز شده و مبلغ تبدیل شده را نمایش میدهد.
این نشان میدهد که چگونه استریم پاسخ به ما امکان میدهد تا با در دسترس قرار گرفتن دادهها، بهروزرسانیهای میانی را به کاربر ارائه دهیم و به تجربه کاربری واکنشگراتر و جذابتری منجر شویم.
مزایای پاسخ فرم پیشرونده
- تجربه کاربری بهبود یافته: بازخورد فوری به کاربران ارائه میدهد و باعث میشود برنامه واکنشگراتر و کمتر کند به نظر برسد.
- کاهش تأخیر محسوس: با نشان دادن نتایج میانی، کاربران فرآیند را سریعتر درک میکنند، حتی اگر زمان کلی عملیات یکسان باشد.
- افزایش تعامل: با ارائه بهروزرسانیهای لحظهای، کاربران را درگیر نگه میدارد و از رها کردن فرم به دلیل تأخیرهای محسوس جلوگیری میکند.
- افزایش نرخ تبدیل: یک تجربه کاربری روانتر و واکنشگراتر میتواند به نرخ تبدیل بالاتر منجر شود، به خصوص برای فرمهای پیچیده.
تکنیکهای پیشرفته
۱. استفاده از `useOptimistic` برای بهروزرسانیهای فوری رابط کاربری
هوک useOptimistic
به شما امکان میدهد تا رابط کاربری را به صورت خوشبینانه قبل از تکمیل اکشن سرور بهروز کنید. این میتواند زمان پاسخ محسوس سریعتری را فراهم کند، زیرا رابط کاربری نتیجه مورد انتظار را بلافاصله منعکس میکند.
import { useOptimistic } from 'react';
function MyComponent() {
const [optimisticState, addOptimistic] = useOptimistic(
initialState,
(state, newUpdate) => {
// بازگرداندن استیت جدید بر اساس بهروزرسانی
return { ...state, ...newUpdate };
}
);
const handleClick = async () => {
addOptimistic({ someValue: 'optimistic update' });
await myServerAction();
};
return (
<div>
<p>{optimisticState.someValue}</p>
<button onClick={handleClick}>Update</button>
</div>
);
}
در مثال مبدل ارز، میتوانید مبلغ تبدیل شده را بر اساس نرخ ارز فعلی به صورت خوشبینانه بهروز کنید و پیشنمایش فوری را قبل از تکمیل محاسبه واقعی در سرور به کاربر ارائه دهید. اگر سرور خطا برگرداند، میتوانید بهروزرسانی خوشبینانه را برگردانید.
۲. پیادهسازی مدیریت خطا و مکانیزمهای جایگزین (Fallback)
پیادهسازی مدیریت خطای قوی و مکانیزمهای جایگزین برای مدیریت مواردی که اکشن سرور با شکست مواجه میشود یا اتصال شبکه قطع میشود، بسیار مهم است. میتوانید از بلوک try...catch
در داخل اکشن سرور برای گرفتن خطاها و بازگرداندن یک پیام خطای مناسب به کلاینت استفاده کنید.
// server/actions.ts
export const convertCurrency = async (prevState: any, formData: FormData) => {
// ...
try {
// ...
} catch (error: any) {
console.error(error);
return { message: 'خطایی هنگام تبدیل ارز رخ داد. لطفا بعدا دوباره تلاش کنید.' };
}
};
در سمت کلاینت، میتوانید پیام خطا را به کاربر نمایش دهید و گزینههایی برای تلاش مجدد یا تماس با پشتیبانی ارائه دهید.
۳. کش کردن نرخهای ارز برای عملکرد بهتر
واکشی نرخهای ارز از یک API خارجی میتواند یک گلوگاه عملکرد باشد. برای بهبود عملکرد، میتوانید نرخهای ارز را با استفاده از یک مکانیزم کشینگ مانند Redis یا Memcached کش کنید. unstable_cache
از Next.js (همانطور که در مثال استفاده شد) یک راهحل کشینگ داخلی فراهم میکند. به یاد داشته باشید که کش را به صورت دورهای باطل کنید تا اطمینان حاصل شود که نرخهای ارز بهروز هستند.
۴. ملاحظات بینالمللیسازی (Internationalization)
هنگام ساخت برنامهها برای مخاطبان جهانی، در نظر گرفتن بینالمللیسازی (i18n) مهم است. این شامل موارد زیر است:
- قالببندی اعداد: استفاده از قالبهای عددی مناسب برای مناطق مختلف (مثلاً استفاده از کاما یا نقطه به عنوان جداکننده اعشار).
- قالببندی ارز: نمایش نمادها و قالبهای ارز متناسب با منطقه کاربر.
- قالببندی تاریخ و زمان: استفاده از قالبهای تاریخ و زمان مناسب برای مناطق مختلف.
- محلیسازی: ترجمه رابط کاربری به زبانهای مختلف.
کتابخانههایی مانند Intl
و react-intl
میتوانند به شما در پیادهسازی i18n در برنامههای ریاکت کمک کنند.
مثالها و موارد استفاده در دنیای واقعی
- تجارت الکترونیک: نمایش هزینههای حمل و نقل و تخمین زمان تحویل به صورت لحظهای همزمان با اضافه کردن آیتمها به سبد خرید توسط کاربر.
- برنامههای مالی: ارائه قیمتهای لحظهای سهام و بهروزرسانیهای پورتفولیو.
- رزرو سفر: نمایش قیمتها و موجودی پروازها به صورت لحظهای.
- تجسم دادهها: استریم بهروزرسانیهای داده به نمودارها و گرافها.
- ابزارهای همکاری: نمایش بهروزرسانیهای لحظهای در اسناد و پروژهها.
نتیجهگیری
استریم پاسخ اکشنهای سرور ریاکت یک راه قدرتمند برای بهبود تجربه کاربری برنامههای ریاکت شما ارائه میدهد. با ارائه پاسخهای فرم پیشرونده، میتوانید فرمهای سریعتر، واکنشگراتر و جذابتری ایجاد کنید که کاربران را درگیر نگه میدارد و نرخ تبدیل را بهبود میبخشد. با ترکیب استریم پاسخ با تکنیکهایی مانند بهروزرسانیهای خوشبینانه و کشینگ، میتوانید تجارب کاربری واقعاً استثنایی بسازید.
همچنان که اکشنهای سرور ریاکت به تکامل خود ادامه میدهند، میتوانیم انتظار ویژگیها و قابلیتهای قدرتمندتری را داشته باشیم که توسعه برنامههای وب پیچیده و پویا را بیش از پیش سادهتر میکنند.
برای مطالعه بیشتر
این راهنما یک نمای کلی جامع از استریم پاسخ اکشنهای سرور ریاکت و کاربرد آن در پاسخهای فرم پیشرونده ارائه میدهد. با درک مفاهیم و تکنیکهای مورد بحث در اینجا، میتوانید از این ویژگی قدرتمند برای ساخت برنامههای وب سریعتر، واکنشگراتر و جذابتر استفاده کنید.