Server State در برابر Client State

در درس‌های قبل این فصل، لایه به لایه با پیچیدگی‌های مدیریت داده سرور آشنا شدیم: Loading/Error، Race Condition، Abort، Caching. در این درس، یک قدم به عقب برمی‌داریم تا دلیل بنیادین این همه پیچیدگی را ببینیم: Server State، از نظر ماهیت، با Stateهای معمولی که تا اینجا در این دوره دیدیم فرق دارد.

Client State: چیزی که React به‌تنهایی مالک آن است

تا پیش از این فصل، تقریباً تمام State هایی که در این دوره دیدیم، Client State بودند: باز یا بسته بودن یک منو، متن داخل یک input، مرحله فعلی یک ویزارد. ویژگی مشترک این‌ها این است که React (و کد خود شما) تنها منبع حقیقت آن‌هاست؛ هیچ سیستم بیرونی همزمان آن را تغییر نمی‌دهد.

Server State: دادهی که جای دیگری «صاحب واقعی» آن است

داده‌ای مثل لیست محصولات یا پروفایل کاربر، اساساً متفاوت است: صاحب واقعی این داده، سرور است، نه کامپوننت React شما. چیزی که در State نگه می‌دارید، فقط یک کپی لحظه‌ای از آن داده است؛ کپی‌ای که ممکن است همین الان، توسط کاربر دیگری یا یک فرایند دیگر در سرور، کهنه شده باشد.

چرا این تفاوت، منبع همان پیچیدگی‌هاست

هر مشکلی که در درس‌های قبل دیدیم، مستقیماً از همین ویژگی سرچشمه می‌گیرد:

  • Loading/Error: چون داده از جایی بیرون از React می‌آید، باید منتظر آن بمانیم و احتمال شکست را بپذیریم.
  • Race Condition: چون چند درخواست به یک منبع بیرونی، ترتیب پاسخشان قابل‌پیش‌بینی نیست.
  • Caching: چون همان داده ممکن است چند بار، در زمان‌های مختلف، از همان منبع بیرونی خواسته شود.
  • بی‌اعتبار شدن (Staleness): چون صاحب واقعی داده، سرور است، کپی محلی ما همیشه ممکن است کهنه باشد؛ موضوعی که اصلاً برای Client State معنا ندارد.

هیچ‌کدام از این مشکلات، برای Client State مثل باز یا بسته بودن یک منو، اصلاً وجود ندارند؛ چون آن مقدار، همیشه و فقط در اختیار React است.

چرا useState تنها به‌تنهایی برای Server State کافی نیست

useState و useReducer، ابزارهایی برای مدیریت یک مقدار محلی هستند؛ هیچ‌کدام خودشان مفهومی از «این داده ممکن است کهنه باشد» یا «همگام‌سازی دوره‌ای با منبع اصلی» ندارند. به همین دلیل، هر بار که این رفتارها لازم شد، مجبور شدیم آن‌ها را دستی، با Effect و منطق اضافه، پیاده‌سازی کنیم.

یک معیار ساده برای تشخیص نوع یک State

پیش از تصمیم‌گیری درباره نحوه مدیریت یک مقدار، این سؤال را بپرسید: اگر این مقدار را فراموش کنم و صفحه را تازه کنم، آیا باید دوباره از جایی بیرون از برنامه بگیرمش؟ اگر پاسخ بله است (مثل لیست سفارش‌های کاربر)، با Server State طرفید. اگر پاسخ نه است و مقدار فقط در همین Session معنا دارد (مثل باز بودن یک Accordion)، با Client State طرفید.

چرا این تمایز اهمیت عملی دارد

وقتی این دو نوع State را از هم تفکیک کنیم، متوجه می‌شویم ابزارهایی که برای Client State طراحی شده‌اند (مثل Context برای به‌اشتراک‌گذاری یک مقدار)، لزوماً بهترین انتخاب برای Server State نیستند؛ چون مسائلی مثل Staleness و Caching را به‌تنهایی حل نمی‌کنند. همین بینش، پایه بحث درس‌های بعدی این فصل است، جایی که الگوها و ابزارهای تخصصی‌تر برای Server State را می‌بینیم.

مثال قابل اجرا

در این مثال، دو نوع State کنار هم دیده می‌شوند: یکی کاملاً محلی (نمایش جزئیات)، دیگری وابسته به یک منبع بیرونی (داده کاربر).

مقایسه Client State و Server State در یک کامپوننت
برای دیدن پیش‌نمایش کامپوننت، روی Run بزنید.

جمع‌بندی

Client State مقداری است که فقط React مالک آن است و هیچ مشکل Staleness یا هم‌زمانی ندارد؛ Server State، کپی لحظه‌ای داده‌ای است که صاحب واقعی آن سرور است و به همین دلیل، همه مشکلاتی که در این فصل دیدیم (Loading، Race Condition، Caching) را با خود می‌آورد. در درس بعدی، چند الگوی رایج برای مدیریت بهتر همین Server State را بررسی می‌کنیم.