Lesson 3 of 7 · 35 min

React Native API Integration, Offline Support and Caching

Call APIs reliably on mobile networks, cache responses and design features that keep working offline.

In this lesson1. Mobile networks are not office Wi-Fi2. Caching with a data fetching library3. Designing for offline4. Errors, loading and user trust

Mobile networks are not office Wi-Fi

Developers usually test on fast, stable connections, but real users move between strong signal, weak signal and none at all. A delivery agent in a basement car park in Gurugram, a nurse in a rural clinic or a commuter on the London Underground will all hit dead zones. Design every API call assuming it can be slow, fail halfway or never return. That mindset shapes timeouts, retries, caching and the way your interface communicates waiting.

Build a single API client module that every feature uses. It should add authentication headers, apply a timeout, parse errors into a consistent shape and refresh expired tokens in one place. When every screen calls fetch directly with its own logic, error handling becomes inconsistent and bugs multiply. A single client also makes it easy to add logging, request IDs and environment switching later.

Caching with a data fetching library

A data fetching library gives you caching for free. When a user opens the orders screen, cached data appears instantly while a fresh request runs in the background. If the request fails, the user still sees the last good data with a clear note that it may be out of date. The example below shows a typed fetch helper with a timeout and a query hook. Check the TanStack Query documentation for current options, because names and defaults can change between major versions.

Be deliberate about cache keys and invalidation. Include every input that changes the result in the key, such as filters, page numbers and the user ID, so different queries never share stale data. After a successful mutation, such as creating an order, invalidate or update the related queries so lists refresh. Clear the whole cache when a user signs out, especially on shared devices used by several staff members in a shop or clinic.

typescript · illustrative
// Illustrative TypeScript. See tanstack.com/query for current APIs.
import { useQuery } from '@tanstack/react-query';

type Order = { id: string; status: string; updatedAt: string };

async function getJson<T>(url: string, token: string): Promise<T> {
  const controller = new AbortController();
  const timer = setTimeout(() => controller.abort(), 10000);
  try {
    const res = await fetch(url, {
      headers: { Authorization: `Bearer ${token}` },
      signal: controller.signal,
    });
    if (res.ok === false) throw new Error(`HTTP ${res.status}`);
    return (await res.json()) as T;
  } finally {
    clearTimeout(timer);
  }
}

export function useOrders(token: string) {
  return useQuery({
    queryKey: ['orders'],
    queryFn: () => getJson<Order[]>('https://api.example.com/orders', token),
    staleTime: 60_000, // show cached data, refetch after a minute
    retry: 2,
  });
}

Designing for offline

Offline support exists on a spectrum, and you should decide early how far along it your app needs to go. Read-only offline is the easiest level: persist the query cache to device storage so the last fetched data is available on launch without a network. Many apps need nothing more. Write offline is harder, because actions taken offline must be queued, sent later and reconciled with changes made by others in the meantime.

For write offline, store each pending action in a durable queue with a unique client-generated ID, and send it when connectivity returns. The server should treat that ID as an idempotency key, so retries never create duplicate orders or payments. Show users which items are pending sync. Decide how to handle conflicts, such as last write wins for simple fields or asking the user when two people edited the same record.

  • Level 1: show cached data when offline
  • Level 2: queue simple actions and sync later
  • Level 3: full local database with two-way sync and conflict rules

Errors, loading and user trust

Every screen that loads data has at least four states: loading, success, empty and error. Design all four. Use skeleton placeholders rather than spinners for lists, show a helpful empty state with a next action, and make error messages specific with a retry button. Use a network status library such as NetInfo to show a small offline banner, but do not rely on it alone, because a device can report a connection that cannot actually reach your server.

Make retries safe on the backend side as well. Any request that changes data should be idempotent or carry an idempotency key, so that a retry after a timeout does not repeat the action. XDQ Labs teams review idempotency on every write endpoint a mobile app uses, because mobile retries are far more common than browser retries. Small details like this are what make an app feel dependable to people working in difficult conditions.

Key takeaways
  • Assume every network call can be slow, fail or never return
  • Use one API client for auth, timeouts, errors and token refresh
  • Let a data fetching library cache and refresh server data
  • Choose your offline level early and use idempotency keys for queued writes
  • Design loading, empty, error and success states for every data screen
Try it

Build a shared API client with a timeout and consistent error objects, then use it in one list screen with a data fetching library. Persist the query cache so the list appears on launch without a network. Turn on airplane mode and check that the screen shows cached data and a clear offline message.

Check your understanding

1. Why centralise API calls in one client module?

2. What prevents duplicate orders when a queued offline action is retried?

3. Why should you not rely only on a network status library?

← PreviousReact Native Navigation and State Management ExplainedNext lesson →React Native Push Notifications, Deep Links and Payments: Key Concepts
XDQ xAgents · AI lab for your company
While you sleep, your AI agents keep working.

From USD 49 or INR 2,999 a month. A person approves every step.

Start free, 14 days →See every agent300 credits · no card needed · prices include taxes🚀 Startup? Free landing page for 30 days →Need custom software or a security review? Send a brief →