fix(react-router): prevent JSON-LD duplication and hydration mismatch in React 19#14806
fix(react-router): prevent JSON-LD duplication and hydration mismatch in React 19#14806Ammar123890 wants to merge 3 commits intoremix-run:mainfrom
Conversation
|
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 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 detectedLatest commit: 039f67b The changes in this PR will be included in the next version bump. This PR includes changesets to release 11 packages
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 |
|
Thank you for signing the Contributor License Agreement. Let's get this merged! 🥳 |
The Problem
Currently, the
<Meta />component rendersscript:ld+jsontags using the stringified JSON content as the Reactkey. In React 19, this creates a critical failure point when combined with CDNs (like Cloudflare) or streaming SSR:keyis derived from the stringified JSON, the server-rendered key (with spaces) does not match the client-hydrated key (minified).<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:
keyforscript:ld+jsonto use the descriptorindex. 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.suppressHydrationWarning={true}to the script tag. This allows React to ignore minor whitespace or character encoding discrepancies introduced by external infrastructure.indexinstead ofJSON.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:
TanStack Router: [Issue #6653 - [Hydration mismatch with scripts in Head](fix: preserve data script content during client hydration
Nuxt-jsonld: [Issue #423 - Duplicate structured data items](Duplicate structured data items in Google structured data test tool ymmooot/nuxt-jsonld#423)
Remix Router: [Issue #14797 - [Duplicate JSON-LD scripts]