Skip to content

fix: cart hydration warnings when promises resolve before hydration - #3983

Open
fredericoo wants to merge 1 commit into
previewfrom
fb-fix-cart-hydration-snapshot
Open

fix: cart hydration warnings when promises resolve before hydration#3983
fredericoo wants to merge 1 commit into
previewfrom
fb-fix-cart-hydration-snapshot

Conversation

@fredericoo

@fredericoo fredericoo commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

TL;DR: Cart data could settle before a retained client subtree hydrated, causing useCart to render different client data from the server HTML.

Before

useCart used the mutable live store for both client reads and React's server snapshot. Promise timing could therefore change the first hydration render and produce a mismatch on /cart.

After

Plain useCart consumers hydrate from the provider's immutable initial snapshot, then update from the live store. useSuspenseCart keeps a separate live selector so resolved cart content still streams without blocking the app shell.

Hydration timing

This is not specifically a one-microtask delay. If async cart data has already settled, plain useCart intentionally hydrates the loading or empty state that produced the server HTML, then useSyncExternalStore reconciles it to the live cart in a follow-up React update. React may complete that update before the browser paints.

useSuspenseCart does not take that path. It reads the live store so streamed cart HTML hydrates against the resolved cart. The Next.js template uses this path for CartContent; plain useCart remains appropriate for UI that can render from the initial snapshot and update immediately afterward.

What this changes

  • Capture the initial cart state used for hydration inside CartProvider.
  • Read readiness and selected cart data atomically in useSuspenseCart.
  • Render the Next.js template's CartContent through its existing Suspense boundaries.
  • Cover early promise settlement, streamed SSR resolution, and both hook hydration paths.

Developer impact

No public API changes. Existing useCart and useSuspenseCart consumers keep their current interfaces. Includes a patch changeset for @shopify/hydrogen because this fixes runtime hydration behavior.

UX impact

Direct cart-page loads no longer log a recoverable hydration error or replace the server-rendered cart subtree. The app shell remains streamed and non-blocking.

Risk

  • The plain and Suspense hooks intentionally use different hydration strategies. Regression coverage locks in both contracts.

How to Test

  1. Run pnpm --filter @shopify/hydrogen build.
  2. Run pnpm --filter @shopify/hydrogen-template-nextjs dev:https.
  3. Add an item to the cart.
  4. Load https://local.tryhydrogen.dev:5173/cart directly.
  5. Confirm the cart renders and the browser console has no hydration mismatch.

@fredericoo
fredericoo force-pushed the fb-fix-cart-hydration-snapshot branch from 16f8a4b to 88bb6a1 Compare September 3, 2026 13:12
@fredericoo
fredericoo marked this pull request as ready for review September 3, 2026 13:13
@fredericoo
fredericoo requested a review from a team as a code owner September 3, 2026 13:13
@fredericoo fredericoo added the gsd:50917 New Hydrogen label Sep 3, 2026
@fredericoo fredericoo self-assigned this Sep 3, 2026
@fredericoo fredericoo changed the title Fix cart hydration when initial data resolves early fix: cart hydration warnings when promises resolve before hydration Sep 3, 2026
@fredericoo
fredericoo force-pushed the fb-fix-cart-hydration-snapshot branch from 88bb6a1 to 8314811 Compare September 4, 2026 18:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant