"بطل تخمين. State management و local storage مش نفس الحاجة. هنا ليه ده مهم وإزاي تختار الحل الصح لتطبيقك."
ترميز سعيد! — Ahmed Fahmy
تخيل ده: عندك مكون بيحتاج يحفظ البيانات. فبتقول "خليني أحط دي في 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
كل واحدة لها مكانها. كل واحدة لها استخدامها.
متى تستخدم: البيانات بتاعتك بس في مكون واحد. ما في مكون تاني محتاج يعرفها.
function Dropdown() {
const [isOpen, setIsOpen] = useState(false)
return (
<>
<button onClick={() => setIsOpen(!isOpen)}>
اضغط هنا
</button>
{isOpen && <ul>...</ul>}
</>
)
}
الفوائد:
أبسط حل
مفيش prop drilling
كل instance بتاعتك بتاخد state منفصل
أسرع أداء
امتى ما تستخدمه: لما مكون تاني محتاج نفس البيانات.
متى تستخدم: مكونين أو أكتر محتاجين نفس البيانات.
function Parent() {
const [count, setCount] = useState(0)
return (
<>
<Counter count={count} setCount={setCount} />
<Display count={count} />
</>
)
}
الفوائد:
بسيط
بدون مكتبات خارجية
المشاكل:
Prop drilling - بتمرر props في كل مكان
كل المكونات بتتحدث لما البيانات تتغير
مكونات غير مرتبطة بتتحدث بدون سبب
امتى ما تستخدمه: لما يكون عندك شجرة عميقة من المكونات.
متى تستخدم: محتاج تمرر البيانات لمكونات كتير بدون 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 - حاجات ما بتتغير كتير.
متى تستخدم: محتاج 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.
متى تستخدم: محتاج البيانات تفضل موجودة بعد ما المستخدم يغلق المتصفح.
الحقيقة المهمة: 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 |
|---|---|---|---|---|---|
مكون واحد | ✅ | ❌ | ❌ | ❌ | ❌ |
مكونات أشقاء | ❌ | ✅ | ✅ | ✅ | ✅ |
شجرة عميقة | ❌ | ❌ | ✅ | ✅ | ✅ |
Global state | ❌ | ❌ | ❌ | ✅ | ✅ |
خارج React | ❌ | ❌ | ❌ | ✅ | ✅ |
Persistence | ❌ | ❌ | ❌ | ✅ | ✅ |
Selective updates | ❌ | ❌ | ❌ | ✅ | ✅ |
عندك:
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.
المصادر: