Streams
For endpoints made with getSSE.
function Activity() {
type Event = StreamEvent<typeof client.activity.get>;
const [events, setEvents] = useState<Event[]>([]);
const feed = useStream(client.activity.get, {}, (event) => {
setEvents((previous) => [event, ...previous].slice(0, 6));
// Someone changed notes, possibly in another tab: refetch what's on screen.
store.refresh(refreshes.notes);
});
return (
<section aria-label="Activity">
<h2>Activity</h2>
{feed.error ? (
<p className="error">
Live updates stopped.{" "}
<button type="button" onClick={feed.reconnect}>
Reconnect
</button>
</p>
) : (
!feed.isStreaming && <p className="muted">Live updates ended.</p>
)}
{events.length === 0 ? (
<p className="muted">Changes to notes show up here as they happen.</p>
) : (
<ul>
{events.map((event) => (
<li key={event.id}>
{event.by} {event.action} “{event.note}”
</li>
))}
</ul>
)}
</section>
);
}
In this example:
- The callback runs for every event. Events are not stored: you decide what to keep, and what to refresh.
store.refresh(...)refetches what's on screen when someone else changed it.- The connection is closed when the component unmounts, and opened again when the arguments change.
- A rejected connection (e.g.
401) throws to the nearest<Boundary>, like a failed read. - A network failure is kept as
error, withisStreaming: false: streams drop, and the page should stay.reconnect()tries again. StreamEventgives you the event type from the server.