top of page

Offline-First React Superpowers: TanStack Query's Local Caching Without API Calls

  • Foto do escritor: RToledoDev
    RToledoDev
  • 7 de out.
  • 1 min de leitura

Hate the endless API spinner? TanStack Query (v5) turns your app into an offline beast with effortless cache persistence to localStorage. Fetch once (or never), store smart, and stay snappy—even on spotty connections.

Hate the endless API spinner? TanStack Query (v5) turns your app into an offline beast with effortless cache persistence to localStorage. Fetch once (or never), store smart, and stay snappy—even on spotty connections.


My modern setup for client-side data magic:


  • PersistQueryClientProvider for Seamless localStorage Sync Wrap your app to auto-save/restore the entire query cache. No manual stringifying!

   import { PersistQueryClientProvider } from '@tanstack/react-query-persist-client';
   import { createSyncStoragePersister } from '@tanstack/query-sync-storage-persister'; // For web/localStorage
  import { QueryClient } from '@tanstack/react-query';
   const queryClient = new QueryClient({
     defaultOptions: {
       queries: { gcTime: 1000 * 60 * 60 * 24 }, // 24h cache
     },
   });
   const persister = createSyncStoragePersister({
     storage: window.localStorage,
   });

   // In your root:
   <PersistQueryClientProvider client={queryClient} persistOptions={{ persister }}>
     <App />
   </PersistQueryClientProvider>

Pro tip: Handles objects, arrays, and auto-syncs across sessions/tabs.

  • useQuery + useMutation for Local Data Flows Treat localStorage like a backend—query it, mutate, and let Query handle the rest.


   import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
   function TodoList() {
     const queryClient = useQueryClient();
     const { data: todos = [] } = useQuery({
       queryKey: ['todos'],
       queryFn: () => JSON.parse(localStorage.getItem('todos') || '[]'),
     });
     const mutation = useMutation({
       mutationFn: (newTodo) => {
         const updated = [...todos, newTodo];
         localStorage.setItem('todos', JSON.stringify(updated));
         return updated;
       },
       onSuccess: (data) => queryClient.setQueryData(['todos'], data),
     });
     return (
       <div>
         {todos.map(todo => <p key={todo}>{todo}</p>)}
         <button onClick={() => mutation.mutate('New Todo!')}>Add Offline</button>
       </div>
     );
   }

Why modern? Optimistic updates, invalidation, and TypeScript out-of-the-box.

Build PWAs that feel native—data sticks around, updates fly. Ideal for mobile or low-data scenarios.

Your go-to TanStack Query trick for local vibes?



Comentários


rails-rtoledo_edited.png

Hi, I'm Rodrigo Toledo

A full-stack developer skilled in both front-end and back-end development, building and maintaining web applications

  • Facebook
  • Youtube
  • LinkedIn
  • Instagram

I don't know everything, help me

I'm always seeking to improve what I build and to refine my skills. Whenever I master something, I share it. And when I don't understand, I dive deep until I do—learning, growing, and helping others along the way.

Subscribe

Thanks for submitting!

bottom of page