router icon indicating copy to clipboard operation
router copied to clipboard

Router: Inline scripts with children render empty placeholder during client-side navigation

Open nikuscs opened this issue 1 month ago โ€ข 1 comments

Which project does this relate to?

Router

Describe the bug

When using inline scripts (with children instead of src) in the head() function, client-side SPA navigation renders empty

Possible cause:

On SPA navigation, empty tags appear in the DOM. But the actual content is appended separately via useEffect, but the rendered placeholder remains empty.

I believe this is the piece of code

  if (!router.isServer) {
    const { src, ...rest } = attrs || {};
    return jsx("script", {
      suppressHydrationWarning: true,
      dangerouslySetInnerHTML: { __html: "" },
  client!
      ...rest
    });
  }

This works for external scripts (src), but inline scripts with children should either:

  1. Render with the actual content: { __html: children }
  2. Return null and rely solely on the useEffect DOM insertion

Your Example Website or App

https://stackblitz.com/edit/github-nzob1mi6?file=src%2Froutes%2F__root.tsx

Steps to Reproduce the Bug or Issue

export const Route = createFileRoute('/blog/$slug')({
    head: () => ({
      scripts: [
        {
          type: 'application/ld+json',
          children: JSON.stringify({ "@type": "Article", "headline":"Test" })
        },
      ],
    }),
  })

Expected behavior

Script tags should contain their children content or not render at all on the client.

Screenshots or Videos

No response

Platform

  • Router / Start Version: 1.140.0
  • OS: macOS
  • Browser: Chrome
  • Browser Version: -
  • Bundler: Vite
  • Bundler Version: ^7.0.0

Additional context

No response

nikuscs avatar Dec 10 '25 23:12 nikuscs

๐Ÿ“ CodeRabbit Plan Mode

Generate an implementation plan and agent prompts for this issue.

  • [ ] Create Plan
Examples

๐Ÿ”— Related PRs

TanStack/router#5095 - fix(router): prevent script tag duplication in SSR and client-side navigation [merged] TanStack/router#5686 - fix(router-core): Catch errors thrown during hydrate [merged] TanStack/router#5895 - fix: script streaming [merged] TanStack/router#5903 - fix(solid-start): fix hydration regression in 1.136.9 [merged] TanStack/router#5980 - fix: fix hydration error by preservering script attrs [merged]

๐Ÿ‘ค Suggested Assignees

  • schiller-manuel
  • jamongsalguclub
  • roduyemi
  • birkskyum

๐Ÿงช Issue enrichment is currently in early access.

To disable automatic issue enrichment, add the following to your .coderabbit.yaml:

issue_enrichment:
  auto_enrich:
    enabled: false

coderabbitai[bot] avatar Dec 10 '25 23:12 coderabbitai[bot]

why is the empty placeholder an issue really? does this cause any issues?

schiller-manuel avatar Dec 13 '25 21:12 schiller-manuel

why is the empty placeholder an issue really? does this cause any issues?

Google could report invalid schemas due to being empty or unable to be parsed. It shouldnt pose a direct penalty. So its not that bad, but i think wroth having a look

edit: actually its not really that bad, because this happens on client side only, ssr always renders the tags correctly

nikuscs avatar Dec 13 '25 22:12 nikuscs