Skip to main content

Prefetch & Auto-Prefetch

prefetch() starts a native request in the background (when available) and lets you consume the result later using the same prefetchKey.

Basics

import { fetch, prefetch } from 'react-native-nitro-fetch';

// 1) Start prefetch
await prefetch('https://httpbin.org/uuid', {
headers: { prefetchKey: 'uuid' },
});

// 2) Consume later
const res = await fetch('https://httpbin.org/uuid', {
headers: { prefetchKey: 'uuid' },
});
console.log('prefetched?', res.headers.get('nitroPrefetched'));

Provide the prefetchKey either as a header or via init.prefetchKey:

await prefetch('https://httpbin.org/uuid', { prefetchKey: 'uuid' });

Auto-Prefetch on App Start

Use prefetchOnAppStart() to enqueue requests so they are fetched on the next app start. This works automatically on both Android and iOS:

import { prefetchOnAppStart } from 'react-native-nitro-fetch';

await prefetchOnAppStart('https://httpbin.org/uuid', {
prefetchKey: 'uuid',
});

Manage the queue:

import {
removeFromAutoPrefetch,
removeAllFromAutoprefetch,
} from 'react-native-nitro-fetch';

await removeFromAutoPrefetch('uuid');
await removeAllFromAutoprefetch();
note

Prefetch is best-effort; if native is unavailable, calls are ignored or fall back to JS fetch. Responses served from prefetch add header nitroPrefetched: true.

Why Prefetch Is Cool

  • Earlier start at app launch: Auto-prefetch can kick off network work immediately when the process starts, before React and JS are ready. On mid-range Android devices (e.g., Samsung A16), we observed the prefetch starting at least ~220 ms earlier than triggering the same request from JS after the app warms up.
  • Smoother navigation: Trigger a prefetch when the user initiates navigation, then serve the prefetched result as the destination screen mounts.

Pattern: Prefetch on Navigation Intent + useQuery

This pattern works well with TanStack Query (react-query). Start prefetch alongside navigation; when the screen loads, the request is already in flight or finished.

// List screen
import { prefetch, fetch as nitroFetch } from 'react-native-nitro-fetch';
import { useNavigation } from '@react-navigation/native';

const PREFETCH_KEY = 'user:42';
const URL = 'https://api.example.com/users/42';

function Row() {
const nav = useNavigation();
return (
<Button
title="Open user"
onPress={async () => {
try {
await prefetch(URL, { headers: { prefetchKey: PREFETCH_KEY } });
} catch {}
nav.navigate('UserDetails', { id: 42 });
}}
/>
);
}

Then, in the destination screen:

// UserDetails.tsx
import { fetch as nitroFetch } from 'react-native-nitro-fetch';
import { useQuery } from '@tanstack/react-query';

const PREFETCH_KEY = 'user:42';
const URL = 'https://api.example.com/users/42';

export function UserDetails() {
const q = useQuery({
queryKey: ['user', 42],
queryFn: async () => {
const res = await nitroFetch(URL, {
headers: { prefetchKey: PREFETCH_KEY },
});
return res.json();
},
});

// If the request was prefetched, this often resolves immediately
// and res.headers.get('nitroPrefetched') === 'true'.
}

Native-side prefetch registration (first-run prefetching)

prefetchOnAppStart() only fires from the second cold launch onward — JS has to run once to seed the queue. To prefetch on the very first launch (fresh install), register URLs from native code before JS boots. Both APIs share the same persistent queue, so JS-side removeFromAutoPrefetch() works on natively-registered entries too.

Android — MainApplication.onCreate():

import com.margelo.nitro.nitrofetch.AutoPrefetcher

override fun onCreate() {
super.onCreate()

AutoPrefetcher.registerPrefetch(
this,
"https://api.example.com/feed",
"feed",
mapOf("Accept" to "application/json")
)

AutoPrefetcher.prefetchOnStart(this) // existing call — drains the queue
loadReactNative(this)
}

iOS — application(_:didFinishLaunchingWithOptions:):

NitroAutoPrefetcher.registerPrefetch(
withUrl: "https://api.example.com/feed",
prefetchKey: "feed",
headers: ["Accept": "application/json"]
)
// No explicit prefetchOnStart() needed — fired automatically after launch.
tip

From Swift, expose NitroAutoPrefetcher via your bridging header with #import <NitroFetch/NitroAutoPrefetcher.h>.

JS consumes the result the same way as before:

const res = await fetch('https://api.example.com/feed', {
headers: { prefetchKey: 'feed' },
});
// res.headers.get('nitroPrefetched') === 'true' on first launch

Android Setup

To enable auto-prefetch on Android, you need to call AutoPrefetcher.prefetchOnStart() from your MainApplication.kt. This kicks off queued requests as early as possible — before React Native and JS have finished loading.

Manual Setup (bare React Native)

Edit android/app/src/main/java/.../MainApplication.kt:

import com.margelo.nitro.nitrofetch.AutoPrefetcher

class MainApplication : Application(), ReactApplication {
// ...

override fun onCreate() {
super.onCreate()
// Start any queued auto-prefetch requests as early as possible
try { AutoPrefetcher.prefetchOnStart(this) } catch (_: Throwable) {}

loadReactNative(this)
}
}
tip

Place the AutoPrefetcher.prefetchOnStart(this) call as early as possible in onCreate() — the earlier it runs, the more network time you save before JS is ready.

Expo Plugin (Android)

If you use Expo, the plugin automatically injects AutoPrefetcher.prefetchOnStart() into MainApplication.kt during expo prebuild — no manual native code changes needed.

Add to your app.json:

{
"plugins": ["react-native-nitro-fetch"]
}