Skip to content

feat(ssr): thread context to hooks in streaming SSR (v3.5.1)#37

Merged
monstercameron merged 1 commit into
masterfrom
react-parity/ssr-stream-context
Jun 25, 2026
Merged

feat(ssr): thread context to hooks in streaming SSR (v3.5.1)#37
monstercameron merged 1 commit into
masterfrom
react-parity/ssr-stream-context

Conversation

@monstercameron

Copy link
Copy Markdown
Owner

Completes SSR hooks (after v3.5.0). Streaming RenderToStream now threads the inherited context map so streamed useContext resolves to the nearest provider (incl. nested override + deferred async boundaries). Full suite + native/wasm pass. Ships as v3.5.1.

🤖 Generated with Claude Code

v3.5.0 ran hooks in the streaming path (RenderToStream) but passed no context, so
a streamed component's GoUseContextValue fell back to the descriptor default. The
streaming state now carries the inherited context map: it is derived at each
ContextProvider boundary (deriveContextValues) and restored after that boundary's
children, and captured per pending async boundary so deferred Suspense content
resolves the same context. resolveComponentElement and the select renderer in the
stream path now receive parseState.contextValues instead of nil.

Streamed useContext now resolves to the nearest provider (incl. nested-provider
override); useState/useRef/useMemo continue to work. Completes the SSR hooks work
begun in v3.5.0. Covered by TestStreamRendersHooksAndContext; full suite passes,
native + wasm build clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@monstercameron monstercameron merged commit 5480630 into master Jun 25, 2026
3 checks passed
@monstercameron monstercameron deleted the react-parity/ssr-stream-context branch June 25, 2026 03:31
monstercameron pushed a commit that referenced this pull request Jul 6, 2026
…=0) (#37)

Since inception no test proved in a REAL browser that ui.Hydrate resumes
server-rendered DOM rather than silently client-rendering it — the exact gap the
js.Value hydration fix addressed but could not verify end to end. This adds:

- examples/shared/hydrationprobe: a deterministic component shared by the server
  (native RenderToString) and client (wasm Hydrate) sides, so its markup is
  byte-identical on both and a correct hydration adopts it verbatim.
- examples/public/hydration-metrics: a wasm fixture that hydrates the probe and
  surfaces the framework-reported hydration metrics (via ui.RegisterSSRObserver) to
  window.
- test/playwrightgo/hydration_metrics_e2e_test: server-renders the probe, serves that
  markup, hydrates it in headless Chromium, and asserts FallbackCount==0 and
  DiscardedNodeCount==0 while ExistingDOMNodeCount>0 (guarding against a false pass on
  an empty root) and the server-rendered text survives.

Verified locally: PASS in Chromium (~6s); negative-verified — injecting a stray
unmatched server node makes it fail ("discarded 1 server node"), so the assertion
bites on a real adoption regression.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants