الوسائط · فصل ٧

الحفظ بعد إعادة التحميل

persist · partialize · migrate · rehydrate
🎯 الهدف: تحفظ جزء من الحالة، وتنقل الشكل القديم، وتتحكم في لحظة الترطيب.

persist يكتب الحالة في تخزين ويرجعها لما الصفحة تفتح. الافتراضي createJSONStorage على localStorage. جالب التخزين بيتنده أول ما يتحتاج، مش وقت تقييم الموديول، عشان السيرفر اللي مش فيه localStorage ما يقعش.

persist.js
import { persist, createJSONStorage } from "zustand/middleware";const useCart = create()(  persist(    (set) => ({      items: [],      draft: "",      add: (item) => set((state) => ({ items: [...state.items, item] })),      setDraft: (draft) => set({ draft }),    }),    {      name: "cart",      storage: createJSONStorage(() => localStorage),      partialize: (state) => ({ items: state.items }),      version: 1,      migrate: (saved, from) => (from < 1 ? { items: saved.list ?? [] } : saved),      skipHydration: false,    },  ),);

name مفتاح فريد في التخزين. partialize يختار اللي يتحفظ. المسودة بتاعة الكتابة متتحفظش. الدوال مش بتتسلسل في JSON أصلًا.

version رقم. لو الرقم في التخزين غير رقم المتجر، النسخة القديمة ما تتطبقش إلا لو migrate رجّعتها بالشكل الجديد.

merge يدمج المحفوظ مع الحالة الحالية. الافتراضي دمج سطحي. لو الشكل متداخل، اكتب الدمج بإيدك.

createJSONStorage بيعمل JSON.parse من غير ما يتحقق من الشكل. بيانات بايظة أو قديمة تعدّي. في الإنتاج، تخزين مخصص يتحقق، بـ Zod مثلًا، قبل ما يرجّع الحالة.

قبل وبعد الترطيب

onRehydrateStorage دالة تتنادى قبل القراءة، وتقدر ترجع دالة تانية بعد ما الحالة ترجع أو الخطأ يحصل.

skipHydration يوقّف الرجوع التلقائي. مفيد لو HTML السيرفر لازم يطابق حالة فاضية، والعميل يملا بعدين.

manual.js
useEffect(() => {  useCart.persist.rehydrate();}, []);

على المتجر، بعد الوسيط، فيه persist.hasHydrated و onHydrate و onFinishHydration و clearStorage و setOptions. امسح التخزين لما تعمل خروج، وبعدين رجّع الحالة الأولى في الذاكرة.

التخزين المخصص كائن فيه getItem و setItem و removeItem. نفس الشكل يحفظ الحالة في هاش العنوان عشان اللينك يتشاف، بدل localStorage. راجع الدوكس لشكل القيمة المخزنة، لأنها ملفوفة مع رقم النسخة.

خلّصت الفصل لما

🧠 اختبر نفسك
١) partialize بتمنع إيه؟
حفظ الحقول اللي مش عايزها تعدّي إعادة التحميل، زي مسودة فورم.
٢) النسخة في التخزين أقدم. مين يظبط الشكل؟
migrate، لو راجعة الحالة بالشكل الجديد. من غيرها النسخة المختلفة ما تتطبقش.
٣) ليه جالب localStorage مش بيتنده وقت الاستيراد؟
عشان السيرفر اللي مش فيه التخزين ما يقعش قبل ما المتجر يتستخدم في المتصفح.