Caching & Stale-While-Revalidate (SWR)

Opt in to response caching, choose a cache-first or stale-while-revalidate strategy, and connect storage adapters that fit your application.


1. Stale-While-Revalidate (SWR) Strategy

Set strategy: 'stale-while-revalidate' to return a stale cached response when one is available while a background request refreshes the cache:

swr.ts
typescript
import { createClient } from 'react-native-fetch-client';

export const api = createClient({
  baseURL: 'https://api.example.com',
  cache: {
    enabled: true,
    defaultTtl: 5 * 60 * 1000, // 5 minutes
    strategy: 'stale-while-revalidate',
  },
});

// Returns a stale cached response when available, then revalidates in the background:
const res = await api.get('/products');
console.log('Served from cache?', res.cached);

2. Persistent Storage Adapters

The cache uses in-memory storage unless you provide a storage adapter. Connect a key-value store such as MMKV, AsyncStorage, or browser localStorage to persist entries:

typescript
import { createClient, type CacheStorageAdapter } from 'react-native-fetch-client';

// Pluggable adapter for MMKV, AsyncStorage, or localStorage:
const appStorage: CacheStorageAdapter = {
  getItem: (key) => storage.getString(key) ?? null,
  setItem: (key, value) => storage.set(key, value),
  removeItem: (key) => storage.delete(key),
};

export const api = createClient({
  baseURL: 'https://api.example.com',
  cache: {
    enabled: true,
    storage: appStorage,
  },
});

3. RFC 7234 Conditional Validation (ETag & 304)

With caching enabled, conditional validation is automatic. If a cached response has an ETag or Last-Modified header, the client sends If-None-Match or If-Modified-Since. Upon receiving an HTTP 304 Not Modified, the cached body is reused without re-downloading bytes over the wire.

4. Declarative Cache Invalidation (invalidate)

When mutating resources, pass cache.invalidate with exact strings or regular expressions to purge stale cached routes:

typescript
// When adding a new product, automatically purge cached feeds:
await api.post('/products', newProduct, {
  cache: { 
    invalidate: ['/products', /^\/categories\/.*/],
  },
});
Automatic Cache Purge
You don't need to manually clear caches in custom hooks. Passing invalidation patterns to your POST / PATCH / DELETE requests keeps your cache synchronized automatically.