Skip to main content
Version: v8.0.0

useStream

The useStream hook consumes streaming responses chunk-by-chunk in React components. It works with any request that uses the fetch adapter's streaming mode, providing both accumulated text (for LLM/SSE use cases) and raw binary chunks (for file downloads).

Purpose
  1. Text streaming: Consume AI/LLM chat responses word-by-word as they arrive.
  2. Binary streaming: Stream file downloads with progress tracking.
  3. Full lifecycle control: Start, abort, and reset streams programmatically.
  4. Reactive updates: Component re-renders as each chunk arrives.

Quick Start

Provide a Request instance and call start() to begin streaming.

AI Chat Streaming
import { useStream } from "@hyper-fetch/react";
import { chatCompletion } from "./api/ai";

function AiChat() {
const { text, streaming, done, start, abort } = useStream(chatCompletion.setPayload({ prompt: "Hello!" }));

return (
<div>
<div className="whitespace-pre-wrap">{text}</div>
{streaming && <p>Streaming...</p>}
{done && <p>Complete!</p>}
<button type="button" onClick={start} disabled={streaming}>
Start
</button>
<button type="button" onClick={abort} disabled={!streaming}>
Stop
</button>
</div>
);
}
Streaming in Core

For the stream to work, the fetch adapter must return a ReadableStream. This happens automatically when the request is sent with streaming: true — the useStream hook handles this for you.


Auto Start

Set autoStart: true to begin streaming immediately when the component mounts. When this option is false (the default), you must call start() manually to initiate the stream.

Auto-starting stream
import { useStream } from "@hyper-fetch/react";
import { getEvents } from "./api/events";

function EventFeed() {
const { text, streaming } = useStream(getEvents, { autoStart: true });

return (
<div>
{streaming && <span>Live</span>}
<pre>{text}</pre>
</div>
);
}
Cleanup on unmount

When the component unmounts, an in-progress stream is automatically aborted, regardless of whether it was started manually or via autoStart.


Resetting State

Use reset() to clear all accumulated data and allow a fresh stream. This also aborts any in-progress stream.

Reset and re-stream
function StreamWithReset() {
const { text, start, reset, done } = useStream(chatRequest);

return (
<div>
<pre>{text}</pre>
{done && (
<button type="button" onClick={() => { reset(); start(); }}>
Stream Again
</button>
)}
</div>
);
}

Non-stream Response Handling

If the server returns a response that is not a ReadableStream (i.e., the response body has no getReader method), the hook gracefully falls back to non-streaming behavior. The response data is converted to a string via JSON.stringify and set as the text value. The chunks array will remain empty, and done will be set to true immediately.

This means useStream is safe to use even when the server might return a regular JSON response instead of a stream - the hook adapts without errors.


Options

OptionTypeDefaultDescription
autoStartbooleanfalseWhen true, the stream starts automatically on mount.

Return Values

PropertyTypeDescription
textstringAccumulated text from all stream chunks decoded as UTF-8.
chunksUint8Array[]Raw binary chunks received from the stream.
streamingbooleanWhether the stream is currently being consumed.
donebooleanWhether the stream has finished (all chunks consumed).
errorError | nullError from the request or stream consumption.
extraobject | nullResponse extra metadata (headers, etc.).
statusnumber | nullHTTP status code from the response.
start() => voidStart consuming the stream.
abort() => voidAbort the ongoing stream.
reset() => voidReset state to initial values, allowing a fresh stream.

See More

useFetch
Learn more about the useFetch hook for standard data fetching.
Adapter
Learn about the fetch adapter and streaming support.