Trong các dự án chia sẻ mã giữa React Web và React Native, việc chọn giải pháp quản lý trạng thái phù hợp quyết định đến tốc độ phát triển và hiệu năng ứng dụng. Zustand cung cấp kho dữ liệu toàn cục nhẹ, không phụ thuộc vào Context API, trong khi React Query lo liệu nạp, cache và đồng bộ dữ liệu từ server. Kết hợp hai thư viện này cho phép tách biệt rõ ràng giữa trạng thái giao diện (UI state) và trạng thái máy chủ (server state). **Tại sao chọn Zustand + React Query?** - Zustand có API đơn giản, hỗ trợ middleware (persist, devtools) và hoạt động giống nhau trên web lẫn native. - React Query tự động xử lý refetch, stale‑while‑revalidate, pagination và mutation, giảm boilerplate so với Redux Toolkit. - Cả hai đều không yêu cầu Provider bao quanh toàn bộ cây component, giúp chia sẻ mã mà không gặp xung đột context. **Kiến trúc đề xuất** 1. **Store UI** – Tạo các store Zustand riêng cho từng feature (theme, modal, form draft). Sử dụng middleware `persist` để lưu cài đặt theme vào `AsyncStorage` (native) hoặc `localStorage` (web). 2. **Store Server** – Không lưu trữ dữ liệu API trong Zustand. Thay vào đó, định nghĩa các hook `useUserQuery`, `usePostsQuery` dựa trên `useQuery` của React Query. Mutation dùng `useMutation` và gọi `queryClient.invalidateQueries` để cập nhật cache. 3. **Bridge** – Khi cần đồng bộ trạng thái UI với server (ví dụ: lưu bản nháp offline), dùng `useEffect` lắng nghe thay đổi từ store Zustand và gọi mutation React Query. **Ví dụ thực tế** ```js // store/themeStore.ts import { create } from 'zustand' import { persist } from 'zustand/middleware' export const useThemeStore = create(persist((set) => ({ dark: false, toggle: () => set((s) => ({ dark: !s.dark })) }), { name: 'theme' })) ``` ```tsx // hooks/usePosts.ts import { useQuery } from '@tanstack/react-query' import { fetchPosts } from '@/api' export const usePosts = () => useQuery({ queryKey: ['posts'], queryFn: fetchPosts }) ``` **Mẹo áp dụng ngay** - Bật `react-query-devtools` trên web và `flipper-react-query` trên native để quan sát cache realtime. - Dùng `select` trong `useQuery` để chỉ subscribe trường cần thiết, tránh render dư thừa. - Cấu hình `staleTime` phù hợp (ví dụ 5 phút) để giảm request không cần thiết khi người dùng chuyển tab. - Với form phức tạp, kết hợp `react-hook-form` và Zustand để giữ draft cục bộ, chỉ gọi mutation khi người dùng bấm lưu. Kết luận: Tách biệt UI state và server state bằng Zustand + React Query mang lại mã sạch, dễ test và hiệu năng ổn định trên cả hai nền tảng. Hãy thử áp dụng trên một feature nhỏ (theme + danh sách bài viết) trước khi mở rộng sang toàn bộ ứng dụng.