1. Vấn đề thường gặp Khi phát triển song song Web (Next.js) và Mobile (Expo), team hay copy‑paste các hàm fetch thủ công. Điều này dẫn đến: - Sai lệch kiểu dữ liệu giữa client và server. - Khó bảo trì khi schema GraphQL thay đổi. - Tăng bộ lọc boilerplate trong từng component. 2. Kiến trúc đề xuất - Sử dụng GraphQL Codegen để sinh TypeScript types và React Query hooks trực tiếp từ schema. - Đặt toàn bộ logic gọi API trong thư mục shared/api, xuất khẩu các hook sẵn sàng dùng. - React Query lo caching, refetch, retry, còn Codegen đảm bảo type‑safe. 3. Cài đặt GraphQL Codegen - Cài đặt: npm i -D @graphql-codegen/cli @graphql-codegen/typescript @graphql-codegen/typescript-operations @graphql-codegen/typescript-react-query - Tạo file codegen.yml ở root monorepo: schema: "https://api.example.com/graphql" documents: "packages/shared/api/**/*.graphql" generates: packages/shared/api/generated.ts: plugins: - typescript - typescript-operations - typescript-react-query - Chạy script: npx graphql-codegen --config codegen.yml 4. Tích hợp React Query - Wrap ứng dụng với QueryClientProvider ở _app.tsx (Next.js) và App.tsx (Expo). - Import hook sinh ra: import { useLoginMutation } from '@/shared/api/generated'; - Sử dụng trong component: const { mutate, isLoading } = useLoginMutation(); const handleSubmit = (data) => mutate(data, { onSuccess: navigateToHome }); 5. Ví dụ thực tế: mutation đăng nhập - File packages/shared/api/mutations/login.graphql: mutation Login($email: String!, $password: String!) { login(email: $email, password: $password) { token user { id name } } } - Sau khi codegen, hook useLoginMutation tự có kiểu biến đầu vào và kiểu trả về chính xác. 6. Lợi ích và lưu ý - Giảm 70% boilerplate so với fetch thủ công. - Type safety xuyên suốt từ schema đến UI. - Dễ dàng mở rộng: thêm query mới chỉ cần file .graphql và chạy codegen. - Cần cấu hình cache key nhất quán giữa Web và Mobile để tránh stale data. - Theo dõi version schema qua CI để phát hiện breaking change sớm.