Async read atom: const userAtom = atom(async (get) => { const id = get(userIdAtom); return await fetchUser(id); }) — component dùng useAtomValue(userAtom) sẽ tự suspend trong khi fetch (cần bọc <Suspense>).
- Đây là tích hợp với React Suspense tự nhiên nhất trong các state libs.
loadable(userAtom)từjotai/utilstrả về{ state: 'loading'|'hasData'|'hasError', data, error }— tránh Suspense khi cần kiểm soát loading UI thủ công.atomWithQuerytừjotai-tanstack-querytích hợp TanStack Query vào atom:const postsAtom = atomWithQuery(() => ({ queryKey: ['posts'], queryFn: fetchPosts })). - Lưu ý: async atom re-fetch mỗi khi dependency atom thay đổi, không có built-in stale-time như React Query — dùng
atomWithQuerynếu cần caching strategy phức tạp.
Async read atom: const userAtom = atom(async (get) => { const id = get(userIdAtom); return await fetchUser(id); }) — a component using useAtomValue(userAtom) will automatically suspend while fetching (requires wrapping with <Suspense>).
- This is the most natural React Suspense integration of any state library.
loadable(userAtom)fromjotai/utilsreturns{ state: 'loading'|'hasData'|'hasError', data, error }— avoids Suspense when you need manual control over the loading UI.atomWithQueryfromjotai-tanstack-queryintegrates TanStack Query into an atom:const postsAtom = atomWithQuery(() => ({ queryKey: ['posts'], queryFn: fetchPosts })).
Pitfall: an async atom refetches whenever a dependency atom changes; there is no built-in stale-time like React Query — use atomWithQuery when you need a more sophisticated caching strategy.