ما هو Zustand؟
Zustand مكتبة صغيرة وسريعة وقابلة للتوسّع لإدارة الحالة في React. تعتمد على واجهة برمجية Minimal تجعل التعلّم والاستخدام سهلين، وتستفيد من Hooks لتوفير طريقة بسيطة لإدارة حالة التطبيق بدون التعقيد والتمهيد الطويل لحلول مثل Redux.
اسم "Zustand" بالألمانية يعني "الحالة"، وهو ما يعبّر بدقة عن هدفها. صُمّمت بلا افتراضات مسبقة وتمنحك الحرية لتنظيم الحالة كما تشاء.
لماذا تختار Zustand؟
- كود متكرر قليل: ابدأ بسرعة بعدة أسطر فقط، ولا حاجة لإجراءات أو مخفضات لتغييرات الحالة البسيطة.
- واجهة مبنية على Hooks: إن كنت تعرف React Hooks فستشعر بالألفة مع Zustand.
- الأداء: تعيد Zustand تصيير المكوّنات فقط عند تغيّر الجزء الذي تشترك به، مما يحسن الأداء.
- حجم حزمة صغير: مكتبة خفيفة لا تضيف حجمًا يُذكر لحزمة تطبيقك.
البدء مع Zustand
أولًا، أضف Zustand إلى مشروعك:
npm install zustand
إنشاء متجر
"المتجر" في Zustand هو Hook يحتفظ بالحالة ودوال تحديثها. إليك مثالًا لمتجر يعدّاد بسيط:
import { create } from 'zustand';
const useCounterStore = create((set) => ({
count: 0,
increment: () => set((state) => ({ count: state.count + 1 })),
decrement: () => set((state) => ({ count: state.count - 1 })),
}));
export default useCounterStore;
في هذا المثال، create
هي الدالة الأساسية في Zustand. تتلقّى دالة تمنحك الاستدعاء set
لتحديث الحالة.
استخدام المتجر داخل مكوّن
يمكنك الآن استخدام useCounterStore
داخل أي مكوّن React للوصول إلى الحالة وتحديثها.
import React from 'react';
import useCounterStore from './useCounterStore';
function Counter() {
const { count, increment, decrement } = useCounterStore();
return (
<div>
<p>Count: {count}</p>
<button onClick={increment}>Increment</button>
<button onClick={decrement}>Decrement</button>
</div>
);
}
export default Counter;
هذا كل شيء! أصبح المكوّن Counter
الآن متصلًا بمتجر Zustand. عند استدعاء increment
أو decrement
ستتحدّث الحالة ويُعاد تصيير المكوّن لعرض القيمة الجديدة.
استخدامات متقدّمة
إجراءات غير متزامنة
تجعل Zustand التعامل مع العمليات غير المتزامنة مثل جلب البيانات سهلًا.
import { create } from 'zustand';
const useUserStore = create((set) => ({
user: null,
loading: false,
fetchUser: async (userId) => {
set({ loading: true });
try {
const response = await fetch(`https://api.example.com/users/${userId}`);
const user = await response.json();
set({ user, loading: false });
} catch (error) {
set({ loading: false });
console.error('Failed to fetch user', error);
}
},
}));
نمط الشرائح (Slices)
للحالات الأكثر تعقيدًا، يمكنك تقسيم متجرك إلى "شرائح" لتحسين التنظيم.
const createCounterSlice = (set) => ({
count: 0,
increment: () => set((state) => ({ count: state.count + 1 })),
});
const createThemeSlice = (set) => ({
theme: 'light',
toggleTheme: () => set((state) => ({ theme: state.theme === 'light' ? 'dark' : 'light' })),
});
const useBoundStore = create((...a) => ({
...createCounterSlice(...a),
...createThemeSlice(...a),
}));
باختيار Zustand، ستبسّط منطق إدارة الحالة، تقلّل الكود المتكرر، وتحسّن أداء تطبيقات React لديك. إنها أداة قوية تتدرّج مع احتياجات مشروعك.