مدل واکنشی به چه معناست، چرا کد همگامسازی حذف میشود و چه زمانی Convex انتخاب درستی است — و چه زمانی نیست.
در معماریهای سنتی، هر تغییر در سرور نیاز به یک مسیر دستی برای رسیدن به مرورگر دارد: یک API بسازید، در کلاینت آن را صدا بزنید، کش را بیاعتبار کنید، دوباره fetch کنید. Convex این مسیر را حذف میکند.
سه نوع تابع در Convex دارید و تفاوتشان مهم است:
وقتی یک mutation داده را تغییر میدهد، همه query هایی که آن داده را خواندهاند خودشان دوباره اجرا میشوند. شما هیچکد همگامسازی نمینویسید.
export const list = query({
args: {},
handler: async (ctx) => {
return await ctx.db.query("products").take(20);
},
});
export const add = mutation({
args: { name: v.string() },
handler: async (ctx, args) => {
return await ctx.db.insert("products", { name: args.name });
},
});
در سمت کلاینت فقط useQuery را صدا میزنید. بعد از اجرای add، فهرست محصولات بدون هیچ کد اضافهای بهروز میشود.
در یک فروشگاه، سبد خرید، موجودی و وضعیت سفارش همیشه بهروز است؛ بدون کد همگامسازی دستی و بدون مدیریت کش سمت کلاینت. همین موضوع در پنل مدیریت هم به کار میآید: وقتی سفارشی ثبت میشود، فهرست سفارشها و آمار داشبورد خودشان تازه میشوند.
در عمل این یعنی حجم زیادی از کد حذف میشود — کدی که در پروژههای معمولی بیشترین باگ را تولید میکند، چون همان منطق در چند جا تکرار شده است.
توابع سرور در محیطی جدا اجرا میشوند و کلیدهای حساس هرگز به مرورگر نمیروند. دسترسی هر تابع را میتوانید با بررسی هویت کاربر کنترل کنید. الگوی درست این است که کنترل دسترسی را در خود تابع سرور بگذارید، نه در رابط کاربری:
const user = await getCurrentUser(ctx);
if (!user || user.role !== "admin") throw new Error("دسترسی ندارید");
پنهانکردن دکمه در رابط کاربری، امنیت نیست؛ فقط تجربه کاربری است.
انتخاب ابزار، انتخاب تعادل است. Convex سرعت توسعه و سادگی همگامسازی میدهد؛ در عوض شما مدل ذهنی واکنشی آن را میپذیرید.
اگر مدل واکنشی را بپذیرید، حجم زیادی کد همگامسازی از پروژهتان حذف میشود و باگهایی که از داده قدیمی میآیند از بین میروند. برای دیدن یک پیادهسازی کامل، پروژه آماده فروشگاهی React + Convex همان معماری را در قالب یک فروشگاه واقعی با سبد خرید و پنل مدیریت نشان میدهد.