The Universal HTTP Client for React Native & Expo
Built for the hardest networking edge-cases across mobile, web, and server: single-flight 401 refresh locks, in-flight deduplication, pluggable SWR caching (MMKV, AsyncStorage, Memory), DevTools privacy, and AI token streaming. Direct Hermes C++ native execution with strict zero dependencies.
When tokens expire, 5 concurrent requests queue behind an asynchronous mutex. Exactly 1 refresh call executes; pending requests replay automatically.
Zero Race Conditionsimport { createClient } from 'react-native-fetch-client';
const api = createClient({
baseURL: 'https://api.example.com',
auth: {
token: () => getStoredToken(),
onTokenExpired: async () => {
// Exactly 1 refresh executes across all concurrent callers
const { accessToken } = await refreshAuthSession();
await saveStoredToken(accessToken);
return accessToken;
},
},
});
// All 3 requests trigger at once -> only 1 refresh call occurs
const [feed, profile, alerts] = await Promise.all([
api.get('/feed'),
api.get('/me'),
api.get('/notifications'),
]);Mobile networking is hostile. Standard fetch isn't enough.
Mobile applications run on unreliable radios, experience background memory reclaims, and suffer race conditions when multiple screen components mount simultaneously. Here is how we engineer around them:
The 401 Refresh Token Stampede
The Bug: 5 components mount -> 5 parallel 401s -> 5 refresh calls -> Session revoked.
When an access token expires, an app often sends multiple API calls at the same millisecond. Traditional Axios interceptors fire multiple refresh token calls, causing backend token rotation to invalidate the session and force an accidental logout.
PII & Secret Leaks in DevTools
The Bug: Credit cards, biometrics, & bearer tokens logged to Flipper / Chrome Inspect.
React Native inspection tools hook global network listeners. In QA builds or staging environments, sensitive payment card numbers, KYC selfie uploads, and bearer tokens are broadcast in cleartext across developer tools.
Redundant Concurrent Flights
The Bug: Header, Sidebar, and Dashboard all request /users/me simultaneously.
Without in-flight deduplication, concurrent screen components trigger duplicate network flights across high-latency cellular connections, exhausting mobile socket limits and wasting battery and cellular bandwidth.
Subway Tunnels & Offline Dropouts
The Bug: App enters a dead zone -> Mutation fails -> User loses state or double-charges.
Mobile devices disconnect unpredictably. Uncontrolled retries cause cascading server crashes and battery drain, while dropped POST/PUT mutations lead to lost user progress or duplicate payments upon reconnect.
How does it stack up against Axios & Fetch?
An honest engineering comparison of architectural trade-offs, bundle footprint, and out-of-the-box mobile resilience capabilities.
| Capability / Metric | react-native-fetch-client | Axios | Native Fetch |
|---|---|---|---|
Runtime Dependencies Zero third-party attack surface, no supply-chain vulnerabilities, zero dependency drift. | 0 (Strict Zero) | 4-6 dependencies | 0 |
Minified + Gzip Size Complete resilience primitives packaged into a lightweight, tree-shakeable bundle. | ~15.6 KB | ~40 KB (+ plugins: ~150 KB) | 0 KB (built-in) |
React Native Architecture Direct TurboModule / Bridgeless C++ execution without legacy XMLHttpRequests serialization. | Native Hermes C++ Fetch | Legacy XHR Bridge Wrapper | Native Hermes C++ Fetch |
Single-Flight 401 Auth Mutex Queues concurrent expired requests; executes exactly 1 refresh; replays pending flights. | Built-in (Atomic Lock) | Manual code (Race-prone) | None |
Async Webhook & State Waiter Polls 3DS payments, KYC verification, & webhooks with backoff, abort criteria, & error suppression. | Built-in (api.waitFor) | Manual while loop | None |
In-Flight Deduplication Coalesces identical concurrent GET requests when multiple screen components mount together. | Built-in (Automatic) | Requires 3rd-party plugin | None |
SWR & Persistent Caching 0ms instant cache response with background revalidation and cold-restart persistence. | Built-in (MMKV / Storage) | Requires 3rd-party plugin | None |
Circuit Breaker Pattern Trips OPEN to prevent battery drain and cascading failures during backend service degradation. | Built-in (Local fail-fast) | None | None |
Safe Tuple Requests Go / Rust inspired ergonomic result tuples that eliminate nested try/catch blocks. | api.safe.* [data, error] | None (try/catch only) | None (try/catch only) |
Offline Mutation Queue Queues mutations offline; replays sequentially with persistent UUID idempotency headers. | Built-in with Idempotency | None | None |
Native AI & SSE Streams Direct token streaming from OpenAI, Anthropic, and Gemini in React Native. | Built-in (AsyncGenerator) | Complex / Node-only | Manual ReadableStream |
Migrate from Axios in 30 seconds. Zero learning curve.
Keep the same mental model, instance methods, and interceptor lifecycle you already know. Switch your import to eliminate legacy XHR bridging and unlock native C++ Fetch speed.
// 1. Requires Axios + axios-retry + axios-cache-interceptor
import axios from 'axios';
const api = axios.create({
baseURL: 'https://api.example.com',
timeout: 10000,
});
// Interceptors with manual 401 refresh queues
api.interceptors.response.use(
(res) => res,
async (err) => {
// ⚠️ Complex manual race-condition handling needed
if (err.response?.status === 401) {
return refreshAndRetry(err.config);
}
return Promise.reject(err);
}
);
const res = await api.get('/users');// 1. Pure zero-dependency Fetch client
import { createClient } from 'react-native-fetch-client';
const api = createClient({
baseURL: 'https://api.example.com',
timeout: 10000,
// Built-in atomic 401 refresh mutex (no race conditions)
auth: {
token: () => getStoredToken(),
onTokenExpired: () => refreshSession(),
},
// Built-in SWR caching, retries, and deduplication
cache: { enabled: true, strategy: 'stale-while-revalidate' },
});
const res = await api.get('/users');Runs natively across all JavaScript runtimes
Upgrade your mobile networking stack today.
Join mobile developers building resilient, zero-dependency apps with single-flight auth refresh, SWR caching, and DevTools privacy.