"بطل تخمين. State management و local storage مش نفس الحاجة. هنا ليه ده مهم وإزاي تختار الحل الصح لتطبيقك."
المشكلة اللي بتحصل في كل مشروع
تخيل ده: عندك مكون بيحتاج يحفظ البيانات. فبتقول "خليني أحط دي في local storage". بتكتب الكود، بتشتغل... بس ما بتشتغل. الصفحة ما بتتحدث. المستخدم بيضغط الزر مليون مرة. ما في حاجة بتحصل.
ليه؟ لأن local storage مش state management. ده شيء مختلف تماماً.
الحقيقة: معظم المطورين بيخلطوا بينهم. بيفتكروا إن local storage بتحل مشكلة state management. غلط. كل واحدة بتحل مشكلة مختلفة.
الفرق الأساسي
State management بتخليك تقول لـ React "البيانات اتغيرت، أعد الرسم". Local storage بتخليك تقول "احفظ دي في المتصفح".
واحدة عن التفاعل. التانية عن الحفظ.
// ❌ ده غلط - local storage بدون state
function Modal() {
const isOpen = localStorage.getItem('isOpen') === 'true'
const handleToggle = () => {
localStorage.setItem('isOpen', !isOpen)
}
return isOpen ? <div>...</div> : null
}
شوف إيه اللي بيحصل؟ بتحفظ في local storage. بس React ما تعرف إن البيانات اتغيرت. الصفحة ما بتتحدث. المستخدم بيشوف نفس الحاجة.
// ✅ ده صح - state مع local storage
function Modal() {
const [isOpen, setIsOpen] = useState(() => {
return localStorage.getItem('isOpen') === 'true'
})
const handleToggle = () => {
const newValue = !isOpen
setIsOpen(newValue)
localStorage.setItem('isOpen', newValue)
}
return isOpen ? <div>...</div> : null
}
الفرق؟ استخدمنا useState. ده بيخليك تقول لـ React "البيانات اتغيرت". بعدين حفظنا في local storage. الاتنين مع بعض.
التسلسل الكامل: من البسيط للمعقد
Local State → Lifted State → Context → Global Store → Persistence
↓ ↓ ↓ ↓ ↓
useState Props pass Context Zustand localStorage
كل واحدة لها مكانها. كل واحدة لها استخدامها.
1. Local State: البداية البسيطة
متى تستخدم: البيانات بتاعتك بس في مكون واحد. ما في مكون تاني محتاج يعرفها.
function Dropdown() {
const [isOpen, setIsOpen] = useState(false)
return (
<>
<button onClick={() => setIsOpen(!isOpen)}>
اضغط هنا
</button>
{isOpen && <ul>...</ul>}
</>
)
}
الفوائد:
أبسط حل
مفيش prop drilling
كل instance بتاعتك بتاخد state منفصل
أسرع أداء
امتى ما تستخدمه: لما مكون تاني محتاج نفس البيانات.
2. Lifting State Up: لما تحتاج تشارك
متى تستخدم: مكونين أو أكتر محتاجين نفس البيانات.
function Parent() {
const [count, setCount] = useState(0)
return (
<>
<Counter count={count} setCount={setCount} />
<Display count={count} />
</>
)
}
الفوائد:
بسيط
بدون مكتبات خارجية
المشاكل:
Prop drilling - بتمرر props في كل مكان
كل المكونات بتتحدث لما البيانات تتغير
مكونات غير مرتبطة بتتحدث بدون سبب
امتى ما تستخدمه: لما يكون عندك شجرة عميقة من المكونات.
3. Context API: الحل الأوسط
متى تستخدم: محتاج تمرر البيانات لمكونات كتير بدون prop drilling.
const ThemeContext = createContext()
function ThemeProvider({ children }) {
const [theme, setTheme] = useState('light')
return (
<ThemeContext.Provider value={{ theme, setTheme }}>
{children}
</ThemeContext.Provider>
)
}
function Button() {
const { theme } = useContext(ThemeContext)
return <button className={theme}>اضغط</button>
}
الفوائد:
ما في prop drilling
بتقدر تحدد الـ scope - ما كل التطبيق محتاج يعرف عن البيانات
native في React
المشاكل:
أي مكون بيستخدم Context بيتحدث لما أي حاجة في Context تتغير
ما تقدر تختار "أنا بس محتاج هذا الجزء"
متى تستخدمه: Theme، auth، locale - حاجات ما بتتغير كتير.
4. Zustand: الحل العام
متى تستخدم: محتاج state حقيقي global. ممكن تستخدمه حتى خارج React.
import { create } from 'zustand'
const useStore = create((set) => ({
count: 0,
increment: () => set((state) => ({ count: state.count + 1 })),
}))
function Counter() {
const { count, increment } = useStore()
return <button onClick={increment}>{count}</button>
}
الفوائد:
حقيقي global
بتقدر تستخدمه خارج React
بتقدر تختار "أنا بس محتاج هذا الجزء" - ما كل المكون بيتحدث
بسيط جداً
متى تستخدمه: Shopping cart، user auth، global UI state.
5. Local Storage: الحفظ الدائم
متى تستخدم: محتاج البيانات تفضل موجودة بعد ما المستخدم يغلق المتصفح.
الحقيقة المهمة: Local storage وحدها ما كافية. لازم تجمعها مع state.
// ❌ ده غلط
function Component() {
const data = localStorage.getItem('data')
return <div>{data}</div>
}
// ✅ ده صح
function Component() {
const [data, setData] = useState(() => {
return localStorage.getItem('data') || ''
})
const handleChange = (newData) => {
setData(newData)
localStorage.setItem('data', newData)
}
return <input value={data} onChange={(e) => handleChange(e.target.value)} />
}
متى تستخدمه:
User preferences (theme، language)
Form drafts
Shopping cart
أي حاجة محتاج تفضل بعد refresh
امتى ما تستخدمه:
Sensitive data (استخدم cookies مع httpOnly)
بيانات كتير (localStorage محدود ~5MB)
بدل state management
جدول المقارنة
الحاجة | Local State | Lifted State | Context | Zustand | + localStorage |
|---|---|---|---|---|---|
مكون واحد | ✅ | ❌ | ❌ | ❌ | ❌ |
مثال من الحياة الحقيقية: تطبيق تسوق
عندك:
Theme (light/dark) - Context
User auth - Zustand
Shopping cart - Zustand + localStorage
Modal open/close - Local state
Form inputs - Local state
// Theme - Context
const ThemeContext = createContext()
function ThemeProvider({ children }) {
const [theme, setTheme] = useState('light')
return (
<ThemeContext.Provider value={{ theme, setTheme }}>
{children}
</ThemeContext.Provider>
)
}
// Auth & Cart - Zustand
const useStore = create((set) => ({
user: null,
cart: [],
setUser: (user) => set({ user }),
addToCart: (item) => set((state) => ({
cart: [...state.cart, item]
})),
}))
// Persist cart to localStorage
const usePersistedCart = create(
persist(
(set) => ({
cart: [],
addToCart: (item) => set((state) => ({
cart: [...state.cart, item]
})),
}),
{ name: 'cart-storage' }
)
)
// Modal - Local state
function ProductModal() {
const [isOpen, setIsOpen] = useState(false)
return isOpen ? <Modal onClose={() => setIsOpen(false)} /> : null
}
// Form - Local state
function CheckoutForm() {
const [email, setEmail] = useState('')
const [address, setAddress] = useState('')
return (
<form>
<input value={email} onChange={(e) => setEmail(e.target.value)} />
<input value={address} onChange={(e) => setAddress(e.target.value)} />
</form>
)
}
أفضل الممارسات
ابدأ بـ local state - أبسط حل أولاً
ارفع state لما تحتاج - بس لما مكون تاني محتاجه
استخدم Context للـ semi-global - Theme، auth
استخدم Zustand للـ global - Shopping cart، UI state
أضف localStorage لما تحتاج persistence - بس مع state
الخلاصة
Local state = مكون واحد
Lifted state = مكونات أخت
Context = semi-global، scoped
Zustand = حقيقي global
Local storage = persistence (مع state دائماً)
اختر الحل الأبسط اللي بيحل مشكلتك. ما تستخدم Zustand لو local state كافي. ما تستخدم local storage بدون state.
المصادر:
ترميز سعيد! — Ahmed Fahmy