معرفی مختصر ابزارهای رایج مدیریت State در اکوسیستم React

در درس‌های قبل این فصل، دیدیم چه زمانی و با چه هزینه‌ای، ممکن است به یک ابزار مدیریت State بیرون از React نیاز پیدا کنیم. در این درس، چند گزینه رایج اکوسیستم React را به‌طور مختصر معرفی می‌کنیم؛ نه برای یاد گرفتن API دقیق هرکدام، بلکه برای داشتن یک نقشه کلی از فضای موجود. بررسی کامل‌تر معیارهای انتخاب، موضوع فصل بیست‌وپنجم خواهد بود.

Redux: الگوی متمرکز و قابل پیش‌بینی

Redux یکی از قدیمی‌ترین و شناخته‌شده‌ترین کتابخانه‌های مدیریت State در اکوسیستم React است. ایده اصلی آن بسیار شبیه همان الگوی Reducer است که در فصل نهم با useReducer دیدیم: یک Store واحد، تغییرات فقط از طریق Actionهای توصیفی، و یک تابع Reducer که State جدید را محاسبه می‌کند؛ با این تفاوت که این الگو در سطح کل برنامه، نه فقط یک کامپوننت، اعمال می‌شود. Redux معمولاً با ابزارهای دیباگ قدرتمندی مثل سفر در زمان همراه است، اما نحو آن نسبتاً پرحجم‌تر از جایگزین‌های جدیدتر است.

Zustand: یک Store ساده‌تر و کم‌حجم‌تر

Zustand رویکردی سبک‌تر دارد: یک Store با نحو نزدیک به یک Hook معمولی ساخته می‌شود و کامپوننت‌ها مستقیماً بخشی از آن را که لازم دارند می‌خوانند، بدون نیاز به Provider یا نحو Action/Reducer جداگانه. این سادگی، منحنی یادگیری کوتاه‌تری نسبت به Redux دارد.

Jotai و Recoil: مدیریت State به‌صورت واحدهای کوچک (Atomic)

برخلاف الگوی یک Store بزرگ و متمرکز، این دسته از ابزارها، State را به واحدهای کوچک و مستقل به نام Atom تقسیم می‌کنند. هر Atom را می‌توان جداگانه خواند یا تغییر داد و کامپوننت‌ها فقط به Atomهایی که واقعاً استفاده می‌کنند وابسته می‌شوند؛ رویکردی که می‌تواند به کاهش Re-renderهای غیرضروری که در فصل سیزدهم دیدیم کمک کند.

MobX: رویکرد واکنشی (Reactive)

MobX با مدل ذهنی متفاوتی کار می‌کند: به‌جای به‌روزرسانی صریح State از طریق توابع مشخص، مقادیر را به‌صورت Observable تعریف می‌کند و هر تغییر مستقیم روی آن‌ها، به‌طور خودکار کامپوننت‌های وابسته را به‌روزرسانی می‌کند. این رویکرد به کدی شبیه‌تر به برنامه‌نویسی شیءگرای سنتی منجر می‌شود، در مقایسه با سبک تابعی و Immutable که در بقیه این دوره دنبال کردیم.

Context + useReducer: یک گزینه کاملاً داخلی

همان‌طور که در فصل نهم دیدیم، ترکیب useReducer و Context می‌تواند بسیاری از همین نیازها را بدون هیچ وابستگی بیرونی برآورده کند. این گزینه، هزینه یادگیری یک API جدید را ندارد، اما برخی قابلیت‌های آماده (مثل ابزارهای دیباگ تخصصی یا بهینه‌سازی‌های خودکار برابر Re-render) را هم ندارد که کتابخانه‌های تخصصی ارائه می‌دهند.

هیچ‌کدام «بهترین» مطلق نیست

نکته‌ای که باید از همین معرفی اولیه روشن باشد: هیچ‌کدام از این ابزارها به‌طور مطلق بر بقیه برتری ندارد. هرکدام Trade-off های متفاوتی دارند (همان‌هایی که در درس قبل به‌طور کلی دیدیم) و انتخاب مناسب، به نیاز پروژه، تجربه تیم، و اندازه برنامه بستگی دارد. مستندات رسمی React نیز معمولاً توصیه می‌کند پیش از رفتن سراغ یک کتابخانه بیرونی، ابتدا امکانات داخلی را امتحان کنید.

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

چون معرفی این کتابخانه‌ها نیازمند نصب بسته‌های بیرونی است که در این محیط ممکن نیست، در عوض همان قابلیت سبد خرید را، این‌بار با ساختاری که به الگوی یک Store ساده (شبیه ایده Zustand) نزدیک است، فقط با ابزارهای خود React شبیه‌سازی می‌کنیم.

شبیه‌سازی الگوی یک Store ساده با useState و Context
import { createContext, useContext, useState } from "react";

const StoreContext = createContext(null);

function useCartStore() {
  const [items, setItems] = useState([]);
  const addItem = (item) => setItems((prev) => [...prev, item]);
  const clear = () => setItems([]);
  return { items, addItem, clear };
}

function StoreProvider({ children }) {
  const store = useCartStore();
  return <StoreContext.Provider value={store}>{children}</StoreContext.Provider>;
}

function useStore() {
  return useContext(StoreContext);
}

function Controls() {
  const { addItem, clear } = useStore();
  return (
    <div>
      <button onClick={() => addItem("محصول")}>افزودن</button>
      <button onClick={clear}>پاک کردن</button>
    </div>
  );
}

function Summary() {
  const { items } = useStore();
  return <p>تعداد آیتم‌ها: {items.length}</p>;
}

function App() {
  return (
    <StoreProvider>
      <Controls />
      <Summary />
    </StoreProvider>
  );
}
برای دیدن پیش‌نمایش کامپوننت، روی Run بزنید.

جمع‌بندی

اکوسیستم React چند رویکرد اصلی برای مدیریت State بزرگ‌تر ارائه می‌دهد: Redux با الگوی متمرکز و قابل پیش‌بینی، Zustand با نحوی ساده‌تر، Jotai/Recoil با رویکرد واحدهای کوچک مستقل، MobX با مدل واکنشی، و ترکیب Context و useReducer به‌عنوان یک گزینه کاملاً داخلی. هیچ‌کدام همیشه برتر نیست و انتخاب باید بر اساس نیاز واقعی پروژه باشد. در درس بعدی، معیارهای مشخص‌تری برای انتخاب ابزار مناسب بر اساس نوع مسئله بررسی می‌کنیم.