[TanStack Start] HMR is not working from root route (__root)
Describe the bug
HMR is not working in root route. only working from normal routes.
Your Example Website or App
https://github.com/TanStack/router/tree/main/examples/react/start-basic-rsc
Steps to Reproduce the Bug or Issue
- Clone (or copy or degit) start-basic-rsc example, install dependencies and run dev server.
- Open http://localhost:3000
- Try to edit from
__root.tsx. I just added a link beside Home.
Expected behavior
In terminal, dev server printed a log about page has reloaded.
[vite] page reload app/routes/__root.tsx
but the changes are not reflected in the browser.
Screenshots or Videos
https://github.com/user-attachments/assets/26aaa1a3-80c1-40af-8dd8-f2403051519e
Platform
- OS: macOs
- Browser: Arc / Chrome
- Version: 126.0.6478.127
Additional context
No response
I'm experiencing this as well, not just in my root route but in any top-level route.
I also have not been able to separate out components/Foo.tsx files and have them hot-reload. The dev console & JS console confirm the HMR event has been emitted and received, but the React JS—even for route sub-components modified in non-route files (e.g. import { FooPage } from '~/components/FooPage';) does not re-render the HMR'ed component.
We just added TanStack router to our vite-based project, and now we are also experiencing this HMR failure. I tried a few different routes, it does seem to only be happening with __root.tsx.
To summarize, we see the following HMR problems with file based routing:
HMR is not triggered when editing
-
routes/__root.tsx -
components/Example.tsximported into anyroutes/**.tsxfile -
routes/_layout.tsx
HMR is triggered when editing
-
routes/index.tsx -
routes/example.example.tsx(@anulman are you sure this doesn't work for any plain route (no_prefix) file?) -
routes/with-directory/example.tsx
Reproduction
All of this can be testet with the Start Basic StackBlitz. Create a new File app/components/Example.tsx:
export function Example() {
return <h1>Changing this will not trigger HMR</h1>
}
Now import this into app/routes/index.tsx and render <Example />:
import { createFileRoute } from '@tanstack/react-router'
import { Example } from '~/components/Example'
export const Route = createFileRoute('/')({
component: Home,
})
function Home() {
return (
<div className="p-2">
<h3>Welcome Home!!!</h3>
<Example />
</div>
)
}
While editing "Welcome Home!!!" will trigger HMR, editing "Changing this will not trigger HMR" will not. The latter shows
[vite] hmr update /app/components/Example.tsx
in the console, but a manual reload is necessary.
Having the same problem for routes/page-a/-component/example.tsx
Bump, this happens on routes at random
can you please test out the package built for this PR whether it fixes the HMR issues you are experiencing: https://github.com/TanStack/router/pull/2286#issuecomment-2336435987
can you please test out the package built for this PR whether it fixes the HMR issues you are experiencing: #2286 (comment)
"@tanstack/router": "github:lithdew/router#main"
Installed as above, still had the same issue though. Updates to pages don't hot reload.
Hmm, yeah looks like I'm not sure how to install your forked version to @tanstack/react-router.
@schiller-manuel I've tried both #2286 and #2316. Both seem to fix the problem in their current state.
@jwtong make sure to unfold the instructions in the comments on how to install from a pr. You can either use install/add with your prefered package manager or change the version in your package.json to the URL provided. E.g. testing the #2316 looks like this in our package.json:
"@tanstack/react-router": "https://pkg.pr.new/@tanstack/react-router@2316",
"@tanstack/react-router-with-query": "https://pkg.pr.new/@tanstack/react-router-with-query@2316",
"@tanstack/start": "https://pkg.pr.new/@tanstack/start@2316",
Make sure all @tanstack packages use the same "version" (rather now PR URL).
@KiwiKilian @schiller-manuel
Tested both https://github.com/TanStack/router/pull/2286 and https://github.com/TanStack/router/pull/2316.
For me, it did not resolve the issue. If I edit a route file (e.g. apps/web/src/routes/_auth._nav.member.clients.index.tsx), I'm still not seeing updates until I refresh the page.
I tested by just adding content inside a <div>Hello</div>
It works for me on #2316 (version 1.58.5 and hash 684eef6) when editing app/routes/_authenticated.index.tsx like just adding some text or changing.
none of those fixed my issue. I'm not using tanstack start, only tanstack router, but i have the exact same problem
For anyone reading this who's looking for a workaround until a fix is merged, you can add the following to your __root.tsx to enable HMR in Tanstack Start:
export const Route = createRootRoute({
// Other route props like the component
// ...
//
scripts: () =>
import.meta.env.DEV
? [
{
type: 'module',
children: `import RefreshRuntime from "/_build/@react-refresh";
RefreshRuntime.injectIntoGlobalHook(window)
window.$RefreshReg$ = () => {}
window.$RefreshSig$ = () => (type) => type`,
},
]
: [],
});
This does the same thing as #2286 and #2316 (albeit in a slightly more hacky way). Once the fix is merged, you should be able to safely remove this code from your __root.tsx again
@MarkSFrancis Lifesaver, been trying to work Start into a side project of mine and was pretty sad about the HMR (but its alpha so who cares). A great fix for now until the team gets it going!
@MarkSFrancis - worked wonders for me trying to get authentication working, as soon as i added useServerFn everything exploded!! Found this issue and things are rolling again
Hi, I'm experiencing the same issue with TanStack/Router. HMR doesn't working when I make changes in __root.tsx. I've tried various combinations of TanStack/Router (version 1.78.3 and below) with Vite (version 5.4.10 and below) using React/React SWC, but nothing has worked. I also tried @MarkSFrancis's workaround without success.
Extracting root route component fixed an issue (thanks Claude):
From:
createRootRoute({
component: () => (<></>)
});
To:
createRootRoute({
component: RootComponent
});
Extracting root route component fixed an issue (thanks Claude):
From:
createRootRoute({ component: () => (<></>) }); To:
createRootRoute({ component: RootComponent });
For me this was the issue in all routes! bless you
Currently, while the page is indeed reloaded upon file modification, it does a full page reload instead of a HMR. But this only happens on regular routes, not the __root route (on which HMR works). Using Tanstack Start
Currently, while the page is indeed reloaded upon file modification, it does a full page reload instead of a HMR. But this only happens on regular routes, not the __root route (on which HMR works). Using Tanstack Start
I am experiencing full reload too. Not sure what am i missing. Using Start
For anyone reading this who's looking for a workaround until a fix is merged, you can add the following to your
__root.tsxto enable HMR in Tanstack Start:export const Route = createRootRoute({ // Other route props like the component // ... // scripts: () => import.meta.env.DEV ? [ { type: 'module', children:
import RefreshRuntime from "/_build/@react-refresh"; RefreshRuntime.injectIntoGlobalHook(window) window.$RefreshReg$ = () => {} window.$RefreshSig$ = () => (type) => type, }, ] : [], }); This does the same thing as #2286 and #2316 (albeit in a slightly more hacky way). Once the fix is merged, you should be able to safely remove this code from your__root.tsxagain
I get type errors when i try to add the script like you did, I tried doing the same thing by replacing scripts with loader or beforeReload but to no avail. i'm using tanstack router( not start) with vite, when I edit and save a component in a file that starts with "-"( inside my routes folder to ignore it) I don't see any changes, not even a full page reload let alone HMR. This is super annoying I guess I can't continue with tanstack router for the time being unfortunately :((
@yassine-safraoui same :(
app/routes/__root.tsx
<head>
...
{import.meta.env.DEV && (
<script
type="module"
dangerouslySetInnerHTML={{
__html: `import RefreshRuntime from "/_build/@react-refresh";
RefreshRuntime.injectIntoGlobalHook(window)
window.$RefreshReg$ = () => {}
window.$RefreshSig$ = () => (type) => type`
}}
/>
)}
</head>
This work for me
@sngmn451 thank you! worked for me too
... {import.meta.env.DEV && (
app/routes/__root.tsx
not for me :((
doing it like this:
function RootComponent() { return ( <> <head> <script type="module" dangerouslySetInnerHTML={{ __html: ``import RefreshRuntime from "/_build/@react-refresh"; RefreshRuntime.injectIntoGlobalHook(window) window.$RefreshReg$ = () => {} window.$RefreshSig$ = () => (type) => type``, }} /> </head> <Outlet />; </> ); }
gives this error:
@MarkSFrancis Thanks!
It didn't work for me at first. I had to marked my Route components for export and now it works!
ie instead of:
export const Route = createFileRoute('/')({
component: RouteComponent,
...
})
function RouteComponent() {
...
}
I had to do:
export const Route = createFileRoute('/')({
component: RouteComponent,
...
})
export function RouteComponent() {
...
}
@timbo-tj I don't think this is what you actually want. I works for the wrong reason: Vite cannot do HMR when you export components and non components in the same file. When you do so, it will fallback to full page reloads, which is why you think reload works. I mean, it does, but it's not HMR.
@notKamui Hmmm, I won't claim to understand what Vite + HMR is doing or why...! but this is my experience:
https://github.com/user-attachments/assets/cd1c3df2-71bc-429d-988a-678d44ab38fd
It doesn't seem like a full page reload. (I need to search for my app again on each page load).
FYI I'm experiencing the same issue (all expect the root routes perform a full reload) when enabling autoCodeSplitting in my tsr.config.json 🫤
{
"autoCodeSplitting": true
}
Any updates on when https://github.com/TanStack/router/pull/2316 will merge?
Will this also fix HMR when using SWC?