Skip to content

Comments

fix(react-router): prevent JSON-LD duplication and hydration mismatch in React 19#14806

Open
Ammar123890 wants to merge 3 commits intoremix-run:mainfrom
Ammar123890:fix/json-ld-hydration-duplication
Open

fix(react-router): prevent JSON-LD duplication and hydration mismatch in React 19#14806
Ammar123890 wants to merge 3 commits intoremix-run:mainfrom
Ammar123890:fix/json-ld-hydration-duplication

Conversation

@Ammar123890
Copy link

@Ammar123890 Ammar123890 commented Feb 16, 2026

The Problem

Currently, the <Meta /> component renders script:ld+json tags using the stringified JSON content as the React key. In React 19, this creates a critical failure point when combined with CDNs (like Cloudflare) or streaming SSR:

  1. Hydration Mismatch (Error Update overview.md to use proper react syntax #418): CDNs often minify HTML by stripping whitespace. Because the key is derived from the stringified JSON, the server-rendered key (with spaces) does not match the client-hydrated key (minified).
  2. Tag Duplication: React 19 treats the <head> and <body> as HostSingletons. When a hydration mismatch occurs on a script within these singletons, React 19 orphans the server node and appends a new client-side node. This results in duplicate LD+JSON blocks, which invalidates SEO structured data.

The Solution

This PR stabilizes meta-tag identity by shifting from content-based keys to position-based keys:

  • Stable Index Keys: Changed the key for script:ld+json to use the descriptor index. This ensures the identity of the tag is tied to its position in the array, which is guaranteed to be consistent between server and client rendering passes.
  • Hydration Shield: Added suppressHydrationWarning={true} to the script tag. This allows React to ignore minor whitespace or character encoding discrepancies introduced by external infrastructure.
  • Unified Stability: Updated the fallback key for standard meta tags to use the index instead of JSON.stringify(metaProps), making the entire <Meta /> component resilient to CDN-induced hydration failures.

Related Issues

This fix aligns with recent architectural changes in other major routing frameworks to support React 19's stricter hydration rules:


@remix-cla-bot
Copy link
Contributor

remix-cla-bot bot commented Feb 16, 2026

Hi @Ammar123890,

Welcome, and thank you for contributing to React Router!

Before we consider your pull request, we ask that you sign our Contributor License Agreement (CLA). We require this only once.

You may review the CLA and sign it by adding your name to contributors.yml.

Once the CLA is signed, the CLA Signed label will be added to the pull request.

If you have already signed the CLA and received this response in error, or if you have any questions, please contact us at hello@remix.run.

Thanks!

- The Remix team

@changeset-bot
Copy link

changeset-bot bot commented Feb 16, 2026

🦋 Changeset detected

Latest commit: 039f67b

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 11 packages
Name Type
react-router Major
@react-router/architect Major
@react-router/cloudflare Major
@react-router/dev Major
react-router-dom Major
@react-router/express Major
@react-router/node Major
@react-router/serve Major
@react-router/fs-routes Major
@react-router/remix-routes-option-adapter Major
create-react-router Major

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@remix-cla-bot
Copy link
Contributor

remix-cla-bot bot commented Feb 16, 2026

Thank you for signing the Contributor License Agreement. Let's get this merged! 🥳

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant