Skip to content

react-router: head() scripts with src re-execute on every client-side navigation #8226

Description

@breken-ai

Which project does this relate to?

Router

Describe the bug

A script declared in a route's head() with src (analytics, tag manager, chat widget, pixel) is removed from <head> and re-executed on every client-side navigation that changes head tags. Analytics count every internal click as a fresh visit; widgets boot over and over.

Live repro on @tanstack/react-router 1.170.32 (Playwright, real Chromium): a root head() with scripts: [{ src: '/track.js' }] where track.js increments window.__trackCount:

AFTER SSR LOAD /:        {"count":1}
AFTER NAV -> /pool/123:  {"count":2}
AFTER NAV -> /:          {"count":3}

count should stay 1. Full repro app + script: https://github.com/breken-ai/tanstack-router-headscripts-repro

Root cause

In packages/react-router/src/Asset.tsx, the Script component's injection useEffect keys off [attrs, children, dataScript]. attrs is a freshly spread object on every head-tag computation, so any navigation that rebuilds head tags re-fires the effect: the cleanup removes the injected <script src> node and the effect appends a new one, which the browser executes again.

Compounding it: after the hydration flip the component renders null, so React removes the SSR-adopted <script> node - the dedup loop (querySelectorAll('script[src]')) can never find the SSR copy, so even the first revisit re-executes. Verified live: right after SSR load, document.head already contains zero /track.js nodes.

Your Example Website or App

https://github.com/breken-ai/tanstack-router-headscripts-repro

Steps to Reproduce the Bug or Issue

  1. npm install && npx vite dev --port 3000
  2. node verify-headscripts.mjs (or click between index and /pool/123 by hand and watch window.__trackCount)
  3. The script executes once per navigation instead of once ever.

Expected behavior

A head() script with src is injected and executed exactly once while its route stays matched, no matter how often head tags are recomputed.

Screenshots or Videos

No response

Platform

  • OS: any (reproduced on Linux, Chromium)
  • Browser: any
  • @tanstack/react-router 1.170.32 (latest) and current main

Additional context

Fix PR incoming: the effect should key off a stable serialization of the script's attributes instead of object identity.

Built by breken, your AI support engineer - breken.ai - this one's on us.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions