[PR #700] [MERGED] fix: don't await createFromReadableStream before hydrateRoot (#695) #783

Closed
opened 2026-05-06 13:10:05 +02:00 by BreizhHardware · 0 comments

📋 Pull Request Information

Original PR: https://github.com/cloudflare/vinext/pull/700
Author: @southpolesteve
Created: 3/28/2026
Status: Merged
Merged: 3/28/2026
Merged by: @southpolesteve

Base: mainHead: fix/695-useeffect-not-firing-after-rsc-hydration


📝 Commits (2)

  • 7c56295 fix: don't await createFromReadableStream before hydrateRoot (#695)
  • 96e238e fix: move effect-test page to app-router-cloudflare example

📊 Changes

3 files changed (+40 additions, -1 deletions)

View changed files

examples/app-router-cloudflare/app/effect-test/page.tsx (+26 -0)
📝 packages/vinext/src/server/app-browser-entry.ts (+1 -1)
📝 tests/e2e/cloudflare-workers/hydration.spec.ts (+13 -0)

📄 Description

Summary

Fixes #695 -- useEffect callbacks never firing after RSC hydration on Cloudflare Workers.

  • createFromReadableStream returns a React thenable, not a resolved component tree. Awaiting it before passing to hydrateRoot blocked hydration until the entire RSC stream was consumed, which prevented passive effects from ever being scheduled.
  • In production on Workers, RSC chunks arrive progressively via injected <script> tags, so the stream takes longer to close -- making the bug reliably reproducible there but not locally (where RSC data is available synchronously in window.__VINEXT_RSC__).
  • The fix is one line: remove the await so the thenable is passed directly to hydrateRoot, matching the React RSC contract and the pattern already used in app-ssr-entry.ts.

Changes

  • packages/vinext/src/server/app-browser-entry.ts -- remove await on createFromReadableStream (line 182)
  • tests/fixtures/cf-app-basic/app/effect-test/page.tsx -- new "use client" fixture page that uses useEffect to flip a status flag
  • tests/e2e/cloudflare-workers/hydration.spec.ts -- regression test that verifies useEffect fires after RSC hydration on the Workers e2e project

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/cloudflare/vinext/pull/700 **Author:** [@southpolesteve](https://github.com/southpolesteve) **Created:** 3/28/2026 **Status:** ✅ Merged **Merged:** 3/28/2026 **Merged by:** [@southpolesteve](https://github.com/southpolesteve) **Base:** `main` ← **Head:** `fix/695-useeffect-not-firing-after-rsc-hydration` --- ### 📝 Commits (2) - [`7c56295`](https://github.com/cloudflare/vinext/commit/7c56295d5a0e3e89d0ddefdef9859638ea1fd0b2) fix: don't await createFromReadableStream before hydrateRoot (#695) - [`96e238e`](https://github.com/cloudflare/vinext/commit/96e238eb6073c0608f11bfffd2112ecf7748dfed) fix: move effect-test page to app-router-cloudflare example ### 📊 Changes **3 files changed** (+40 additions, -1 deletions) <details> <summary>View changed files</summary> ➕ `examples/app-router-cloudflare/app/effect-test/page.tsx` (+26 -0) 📝 `packages/vinext/src/server/app-browser-entry.ts` (+1 -1) 📝 `tests/e2e/cloudflare-workers/hydration.spec.ts` (+13 -0) </details> ### 📄 Description ## Summary Fixes #695 -- `useEffect` callbacks never firing after RSC hydration on Cloudflare Workers. - `createFromReadableStream` returns a React **thenable**, not a resolved component tree. Awaiting it before passing to `hydrateRoot` blocked hydration until the entire RSC stream was consumed, which prevented passive effects from ever being scheduled. - In production on Workers, RSC chunks arrive progressively via injected `<script>` tags, so the stream takes longer to close -- making the bug reliably reproducible there but not locally (where RSC data is available synchronously in `window.__VINEXT_RSC__`). - The fix is one line: remove the `await` so the thenable is passed directly to `hydrateRoot`, matching the React RSC contract and the pattern already used in `app-ssr-entry.ts`. ## Changes - `packages/vinext/src/server/app-browser-entry.ts` -- remove `await` on `createFromReadableStream` (line 182) - `tests/fixtures/cf-app-basic/app/effect-test/page.tsx` -- new `"use client"` fixture page that uses `useEffect` to flip a status flag - `tests/e2e/cloudflare-workers/hydration.spec.ts` -- regression test that verifies `useEffect` fires after RSC hydration on the Workers e2e project --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
BreizhHardware 2026-05-06 13:10:05 +02:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/vinext#783
No description provided.