react-native-nitro-fetch is a general purpose network fetching library for React Native. It can be used as a drop-in replacement for the built-in fetch(...) method, as well as provide additional features like prefetching and workletized mappers.
- 🔧 Drop-in replacement for the built-in
fetch(...)method - ⚡️ Fast HTTP stack using Cronet on Android, and URLSession on iOS
- 💪 Supports HTTP/1, HTTP/2 and HTTP/3 over QUIC, Brotli, and disk cache
- ⏰ Prefetching on app-startup for even faster initialization
- 🧵 Worklet support for parallel data mapping without blocking the JS Thread
- 🔥 Powered by Nitro Modules
npm i react-native-nitro-fetch react-native-nitro-modulesNitro Modules requires react-native 0.75+ or higher
To simply fetch data, import the fetch(...) method from react-native-nitro-fetch:
import { fetch } from 'react-native-nitro-fetch' const res = await fetch('https://httpbin.org/get') const json = await res.json()This can be used as a drop-in-replacement for the built-in fetch(...) method.
You can prefetch a URL in JS, which keeps the result cached for the next actual fetch(...) call - this can be used shortly before navigating to a new screen to have results hot & ready:
import { prefetch } from 'react-native-nitro-fetch' await prefetch('https://httpbin.org/uuid', { headers: { prefetchKey: 'uuid' } })Then, on the new screen that was navigated to:
import { fetch } from 'react-native-nitro-fetch' const res = await fetch('https://httpbin.org/uuid', { headers: { prefetchKey: 'uuid' } }) console.log('prefetched header:', res.headers.get('nitroPrefetched'))Prefetching data on app launch (or process start) will make it hot & ready once your JS code actually runs. Call prefetchOnAppStart(...) to enqueue a prefetch for the next app start:
import { prefetchOnAppStart } from 'react-native-nitro-fetch' await prefetchOnAppStart('https://httpbin.org/uuid', { prefetchKey: 'uuid' })Then, once the app opens the next time, a call to fetch(...) might resolve faster since it will contain already cached results:
import { fetch } from 'react-native-nitro-fetch' const res = await fetch('https://httpbin.org/uuid', { headers: { prefetchKey: 'uuid' } }) console.log('prefetched header:', res.headers.get('nitroPrefetched'))In our tests, prefetching alone yielded a ~220 ms faster TTI (time-to-interactive) time! 🤯
Cancel in-flight requests using the standard AbortController API:
import { fetch } from 'react-native-nitro-fetch' const controller = new AbortController() // Abort after 500ms setTimeout(() => controller.abort(), 500) try { const res = await fetch('https://httpbin.org/delay/20', { signal: controller.signal, }) } catch (e) { if (e.name === 'AbortError') { console.log('Request was cancelled') } }Pre-aborted signals are also supported — the request will throw immediately without making a network call:
const controller = new AbortController() controller.abort() await fetch(url, { signal: controller.signal }) // throws AbortErrorUpload files and form fields using FormData:
import { fetch } from 'react-native-nitro-fetch' const fd = new FormData() fd.append('username', 'nitro_user') fd.append('avatar', { uri: 'file:///path/to/photo.jpg', type: 'image/jpeg', name: 'avatar.jpg', } as any) const res = await fetch('https://httpbin.org/post', { method: 'POST', body: fd, }) const json = await res.json()Since Nitro Fetch is a Nitro Module, it can be used from Worklets. This can be useful to parse data without blocking the main JS-Thread:
import { nitroFetchOnWorklet } from 'react-native-nitro-fetch' const data = await nitroFetchOnWorklet( 'https://httpbin.org/get', undefined, (payload) => { 'worklet' return JSON.parse(payload.bodyString ?? '{}') } )Before using worklet mapping, install and configure react-native-worklets.
Nitro Fetch can also expose an streaming mode that returns a ReadableStream body.
Combined with react-native-nitro-text-decoder, you can incrementally decode UTF‑8 chunks:
import { useRef, useState } from 'react' import { fetch as nitroFetch } from 'react-native-nitro-fetch' import { TextDecoder } from 'react-native-nitro-text-decoder' export function StreamingExample() { const [output, setOutput] = useState('') const decoder = useRef(new TextDecoder()) const append = (text: string) => { setOutput(prev => prev + text) } const runStream = async () => { // `stream: true` enables the streaming transport const res = await nitrofetch('https://httpbin.org/stream/20', { stream: true, }) const reader = res.body?.getReader() if (!reader) { append('No readable stream!') return } let chunks = 0 while (true) { const { done, value } = await reader.read() if (done) break chunks++ const text = decoder.current.decode(value, { stream: true }) append(text) } append(`\n\n✅ Done — ${chunks} chunk(s) received`) } // Call `runStream()` from a button handler in your UI }Nitro Fetch is currently in an alpha stage. You can adopt it in production, but keep in mind that the library and it's API is subject to change.
- WebSockets are not supported. For high‑performance sockets and binary streams, consider using react-native-fast-io by our friends at Callstack.
- Getting Started
- API Reference
- Android Details
- iOS Details
- Prefetch & Auto-Prefetch
- Worklets
- Troubleshooting
- Cronet (Android) notes
- Cronet (iOS) notes
Nitro Fetch is built with ❤️ by Margelo. We build fast and beautiful apps. Contact us at margelo.com for high-end consultancy services.
- Development workflow:
CONTRIBUTING.md#development-workflow - Sending a pull request:
CONTRIBUTING.md#sending-a-pull-request - Code of conduct:
CODE_OF_CONDUCT.md
MIT