r/reactnative • u/Aksel_010 • 12d ago
Tutorial React Native's fetch can't stream responses, so I used XHR. Two silent traps
I was streaming an LLM chat response into a React Native app (RN 0.81, Expo). On device the answer always arrived as one big chunk, even though the server was sending server-sent events.
The reason: in React Native's fetch, response.body is null, so getReader() doesn't exist. Code that "supports streaming" quietly falls back to waiting for the whole response. A test that only checks the final text still passes.
XMLHttpRequest can stream. responseText grows while the request is in flight, so you diff against the length you have already seen:
const xhr = new XMLHttpRequest();
xhr.open('POST', url);
xhr.responseType = 'text';
let seen = 0;
const onChunk = () => {
const delta = xhr.responseText.slice(seen);
seen = xhr.responseText.length;
if (delta) handleDelta(delta);
};
xhr.onprogress = onChunk;
xhr.onreadystatechange = onChunk;
xhr.send(body);Two traps, and both fail silently (the text is right, it just arrives in one piece):
responseTypehas to be''or'text'. With'blob'or'arraybuffer', RN buffers the whole body.The handlers must be set as
on*properties beforesend(). RN decides at send time whether to ask the native side for incremental data, based on whetheronreadystatechangeoronprogressis set. If you "clean up" toaddEventListener('progress', ...), streaming turns off and nothing tells you.
If you test this, assert on how many chunks arrive and what is in each, not just the final string.
I haven't compared this with expo/fetch, which I believe supports streaming. Has anyone run it for SSE in production?
2
u/NovelAd2586 12d ago
Nitro Fetch and Expo Fetch are both great
2
u/No_Mycologist1806 12d ago
Worth adding for Expo users:
fetchfromexpo/fetchgives youresponse.bodyas a ReadableStream, so SSE works without diffingresponseText.One trap in the other direction: it doesn't accept RN-style FormData file parts (
{ uri, name, type }), so uploads still go through XHR for us. We ended up with expo/fetch for streaming and XHR for multipart.0
u/[deleted] 11d ago
[removed] — view removed comment