بازگشت به وبلاگ

مقایسه‌ی مدیریت state: Redux Toolkit در برابر Zustand و Jotai

۲ مرداد ۱۴۰۵3 دقیقه مطالعه
مقایسه‌ی مدیریت state: Redux Toolkit در برابر Zustand و Jotai

«از کدوم state manager استفاده کنم؟» در واقع سه تا سوال جداست که زیر یه بارونی قایم شدن: چقدر boilerplate حاضرم بنویسم، به time-travel debugging نیاز دارم یا نه، و state من واقعاً global هست یا فقط بین چندتا کامپوننت نزدیک به هم شریکه؟ Redux Toolkit، Zustand و Jotai به این سوال‌ها خیلی متفاوت جواب می‌دن.

Redux Toolkit — یه استور مرکزی، همه‌چیز صریح

Redux Toolkit (RTK) روش مدرن و opinionated نوشتن Redux‌ه: boilerplate کمتر از Redux کلاسیک، ولی همون ایده‌ی اصلی — یه استور واحد، action هایی که توضیح می‌دن چه اتفاقی افتاده، و reducer هایی که تصمیم می‌گیرن state چطور تغییر کنه.

// store/counterSlice.ts
import { createSlice } from "@reduxjs/toolkit";

const counterSlice = createSlice({
  name: "counter",
  initialState: { value: 0 },
  reducers: {
    increment: (state) => { state.value += 1; }, // پشت‌صحنه از Immer استفاده می‌کنه — این "mutation" امنه
    incrementBy: (state, action: { payload: number }) => { state.value += action.payload; },
  },
});

export const { increment, incrementBy } = counterSlice.actions;
export default counterSlice.reducer;

// داخل یه کامپوننت
const count = useSelector((state: RootState) => state.counter.value);
const dispatch = useDispatch();
dispatch(increment());

Zustand — استوری که فقط یه هوکه

Zustand تشریفات رو کنار می‌ذاره. یه استور فقط یه تابعه؛ کامپوننت‌ها فقط به همون بخشی که می‌خونن subscribe می‌شن، پس بدون memoization اضافه، ری‌رندرها کمینه می‌مونه.

// store/useCounterStore.ts
import { create } from "zustand";

const useCounterStore = create<{ value: number; increment: () => void }>((set) => ({
  value: 0,
  increment: () => set((s) => ({ value: s.value + 1 })),
}));

// داخل یه کامپوننت — فقط وقتی `value` عوض بشه ری‌رندر می‌شه
const count = useCounterStore((s) => s.value);
const increment = useCounterStore((s) => s.increment);

Jotai — state به‌شکل atom، نه یه آبجکت بزرگ

Jotai مدل رو برعکس می‌کنه: به‌جای یه استور که همه‌چیز رو نگه داره، state توی atom های کوچیک و مستقل زندگی می‌کنه که با هم ترکیب می‌شن. نیازی به selector نیست — کامپوننتی که یه atom رو می‌خونه فقط وقتی همون atom عوض بشه ری‌رندر می‌شه.

// atoms/counter.ts
import { atom, useAtom } from "jotai";

const countAtom = atom(0);
const doubledAtom = atom((get) => get(countAtom) * 2); // atom مشتق‌شده، خودکار دوباره محاسبه می‌شه

// داخل یه کامپوننت
const [count, setCount] = useAtom(countAtom);
const [doubled] = useAtom(doubledAtom);

مقایسه کنار هم

Redux Toolkit

Zustand

Jotai

مدل ذهنی

یه استور global، action + reducer

استور یعنی یه هوک

state به‌شکل atom های ترکیب‌پذیر

Boilerplate

متوسط (slice، ولی خیلی کمتر از Redux کلاسیک)

کمینه

کمینه

حجم باندل (تقریبی)

~۱۱ کیلوبایت (+ React-Redux)

~۱ کیلوبایت

~۳ کیلوبایت

DevTools / time travel

عالی (Redux DevTools)

پایه، از طریق middleware

پایه، از طریق ابزار devtools

منطق async

built-in (createAsyncThunk / RTK Query)

دستی، یا یه middleware

دستی، atom ها می‌تونن ذاتاً async باشن

ری‌رندر دقیق

نیاز به selector دقیق

خودکار به‌ازای هر slice

خودکار به‌ازای هر atom

بهترین مورد استفاده

اپ‌های بزرگ، state پیچیده‌ی مشترک، تیم‌هایی که ساختار سخت‌گیرانه می‌خوان

اپ‌های کوچک تا متوسط، اتخاذ سریع، تشریفات کمینه

state رابط‌کاربری با وابستگی زیاد بین بخش‌ها (فرم‌های چندمرحله‌ای، فیلترها)

واقعاً کدوم؟

  • وقتی state واقعاً cross-cutting هست، تیم بزرگ‌تر از دو-سه نفره، و می‌خوای از cache گیری RTK Query برای داده‌ی سرور هم استفاده کنی، برو سراغ Redux Toolkit.

  • وقتی می‌خوای state سراسری داشته باشی بدون تشریفات، برو سراغ Zustand — اکثر پروژه‌های شخصی و اپ‌های متوسط اینجا فرود میان.

  • وقتی state‌ت ذاتاً یه گراف از مقادیر کوچیک و مشتق‌شده‌ست — فرم‌های چندمرحله‌ای، پنل فیلتر، هرجایی که فیلدها به هم وابسته‌ان — برو سراغ Jotai.

  • و قبل از سراغ هرکدومشون رفتن: چک کن ببین واقعاً state گلوباله، یا فقط prop/context‌ایه که چندتا سطح پایین‌تر پاس داده می‌شه — همه‌چیز نیاز به استور نداره.

بهترین state manager، کوچیک‌ترینیه که مسئله‌ی فعلی رو قابل‌فهم می‌کنه. کاملاً اوکیه — حتی خوبه — که برای بخش‌های مختلف یه اپ از ابزارهای متفاوت استفاده کنی.