Skip to learning content
Learning StudioCourses and practice
Experiences

React · Streaming and scheduling

Streaming React

A good chat UI turns a fast token stream into smooth, accessible screen updates while still handling cancellation and completion correctly.

Evidence & limits
What the further reading establishes
ReadableStream lets you read chunks as they arrive, cancel the stream, and work with backpressure.
What this lab runs
A fixed trace compares bursty, steady, stalled, and cancelled delivery. It shows every screen update, scroll decision, live announcement, and cleanup result.
What it does not prove
This fixed lab doesn't benchmark every mix of browser, renderer, and assistive technology.

Dataset

Render Trace

Source
Course-authored synthetic stream
License
Not separately licensed
Size
60 deltas · 4 timing profiles

Further reading

  • Using readable streams

    Primary · MDN Web Docs · Current

    Shows how to read, cancel, and build asynchronous streams in the browser.

  • Streams Standard

    Specification · WHATWG · Living standard

    The official rules for chunks, readers, queues, cancellation, and backpressure.

  • useTransition

    Guide · React · Current

    Explains how non-blocking renders can keep the UI responsive during frequent updates.

Lesson progressRestoring progress…

  1. CodeRestoring
  2. ExperimentRestoring
  3. CheckRestoring

Summary

Keep parsing out of React. The transport sends events as they arrive. The read loop should turn them into app actions for React. React shouldn't parse raw bytes or wait for one giant response string.

Don't render every piece. Dispatching every subword can cause extra renders and a jumpy layout. A small requestAnimationFrame buffer keeps every piece in order while grouping screen updates.

Respect the reader's scroll. Only keep auto-scrolling when the reader is still near the bottom. If someone scrolls up to read earlier content, don't yank them back down.

One animation-frame commitTyped token events are already parsed. The UI queue keeps their exact text until one animation-frame callback sends a render delta; scrolling, announcements, and cancellation remain separate policies.
t = 2 mstoken · "A"t = 7 mstoken · " causal"t = 11 mstoken · " €"
  1. 1
    Typed token eventst=2 ‘A’ · t=7 ‘ causal’ · t=11 ‘ €’
  2. 2
    Pending render-delta queue[‘A’, ‘ causal’, ‘ €’] · order retained
  3. 3
    requestAnimationFramet=16 ms · flush once
  4. 4
    Reducer dispatchTOKEN_BATCH · delta ‘A causal €’
  5. 5
    Screen updateone render · announcement stays limited
Queue before frame["A", " causal", " €"]One reducer action{ type: "TOKEN_BATCH", delta: "A causal €" }Visible resultA causal €
Scroll-follow check24 px ≤ 80 px ∧ userScrolledUp false → followchecked separately after the visual updateLive region“Assistant: A causal €”one short, meaningful announcement instead of three token announcements
Complete flush pending text → dispatch final batch → announce completion.Cancel drop pending text → cancel scheduled frame → reject late deltas.

Group accessible updates. Announcing every token can overwhelm assistive technology. Send the live region meaningful batches, then make one final completion announcement.

Knowledge check

What's the main reason to group streaming deltas before sending a React update?

Implementation

product/streaming-react.py
0 of 2 exercises verifiedOpen coding workspace →

Combine token deltas into one screen update per frame.

Signature
def flush_token_buffer(pending):
Inputs
pending list[str] in arrival order
Returns
{text: str, remaining: []}
Rule
concatenate with no separator and return a fresh empty queue
Example
["Hel","lo"," ","world"] → {text: "Hello world", remaining: []}
Render buffer progressive practice rounds
Restoring saved code…
Reference solution

Approach Combine token deltas into one screen update per frame.

def flush_token_buffer(pending):    return {"text": "".join(pending), "remaining": []}

Build delta buffering and scroll-follow rules in Python, then compare transport events with the updates React would actually render.

Saved results

Results created after your saved code passes its checks

The replay is course data. The validation result is tied to the code you saved and checked.

Loading…