هناك أمر يجب توضيحه TanStack Query هي أدارة لإدارة حالة التطبيق لكن هي async أي بيانات لا تصل إليها مباشرًة بل من الخادم، بينما لو لديك بيانات non-async فلا حاجة إليها استخدم Zustand، وللعلم تستطيع استخدام كلاهما لا مشكلة.
أيضًا لما لا تستخدم RTK Query معRedux Toolkit.
createContext مع localStorage حل مقبول للمشاريع الصغيرة إلى المتوسطة، خاصةً لو البيانات محدودة ولا تحتاج إلى تحديثات متكررة، أي لا يتطلب إضافة مكتبات خارجية ويدعم تحديث الواجهة تلقائيًا عند تغيير الحالة ويناسب الحالات البسيطة مثل تخزين بيانات المستخدم الأساسية.
لكن هناك سلبيات منها إعادة التصيير Re-renders، حيث أي تغيير في الحالة يؤدي إلى إعادة تصيير جميع المكونات المشتركة في الـ contextK ,يحتاج إلى تعليمات يدوية لمزامنة الحالة مع localStorage مثل useEffect.
أيضًا localStorage غير مشفر، وذلك يعرض البيانات الحساسة للاختراق ويفضل استخدام HTTP-only Cookies للـ Tokens.
بالتالي الأفضل استخدام Zustand مع Middleware للتخزين المحلي وهو الأنسب للمشاريع المتوسطة والكبيرة.
import { create } from 'zustand';
import { persist } from 'zustand/middleware';
const useAuthStore = create(
persist(
(set) => ({
user: null,
login: (user) => set({ user }),
logout: () => set({ user: null }),
}),
{
name: 'auth-storage',
getStorage: () => localStorage,
}
)
);
const user = useAuthStore((state) => state.user);
أو دمج TanStack Query مع التخزين المحلي باستخدام onSuccess في mutation وستتمكن من تسجيل الدخول لحفظ البيانات مباشرة في localStorage، واستخدام QueryClient لقراءتها لاحقًا.
const { mutate: login } = useMutation({
mutationFn: loginApi,
onSuccess: (data) => {
localStorage.setItem('user', JSON.stringify(data.user));
queryClient.setQueryData(['user'], data.user);
},
});
const user = JSON.parse(localStorage.getItem('user') || 'null');
const queryClient = useQueryClient();
queryClient.setQueryData(['user'], user);