Which project does this relate to?
Router (also reproduces under Start)
Describe the bug
On the client, lazyRouteComponent clears loadPromise in its import .then, and Lazy only calls use() while comp is unset. If React restarts the render on a fiber that suspended through use(), Lazy now skips use(), and React 19 logs:
This library called use() to suspend in a previous render but did not call use() when it finished. This indicates an incorrect use of use(). Learn more: https://react.dev/warnings/conditional-use-of-use
This happens when a transition suspends on a lazy route component inside a Suspense boundary that is already showing content, the import resolves, and a second transition lands before React retries.
Your Example Website or App
https://github.com/alebedev/tanstack-lazy-use-repro
Steps to Reproduce the Bug or Issue
npm install && npm run dev
- Open http://localhost:3000 with the DevTools console open.
- Click Run repro.
src/routes/index.tsx holds the import behind a gate so the timing is deterministic: a transition renders <Lazy /> (it suspends), then the gate opens and a second startTransition runs in the same tick.
Expected behavior
No warning. Lazy should call use() on every render that follows one where it suspended through use().
Actual behavior
The error above is logged every time (3/3 runs in headless Chromium; npm run check in the repo automates it).
Proposed fix
Keep the fulfilled promise on the client, and call use() on it after it has resolved. React set status = 'fulfilled' when it tracked the thenable, so this use() returns synchronously and never suspends an already loaded component:
loadPromise = importer()
.then((res) => {
if (!(isServer ?? typeof window === 'undefined')) {
- loadPromise = undefined
;(lazyComp as any).preload = undefined
}
comp = res[exportName ?? 'default']
})
@@
} else {
throw load()
}
+ } else if (reactUse && (loadPromise as any)?.status === 'fulfilled') {
+ reactUse(loadPromise)
}
With this applied to node_modules, the repro no longer warns and the component still renders. We've been running it as a local patch in production. Happy to open a PR.
Platform
- @tanstack/react-router: 1.170.39
- @tanstack/react-start: 1.168.58
- react / react-dom: 19.3.0
- vite: 8.3.0
- Browser: Chromium (Playwright 1.62)
Which project does this relate to?
Router (also reproduces under Start)
Describe the bug
On the client,
lazyRouteComponentclearsloadPromisein its import.then, andLazyonly callsuse()whilecompis unset. If React restarts the render on a fiber that suspended throughuse(),Lazynow skipsuse(), and React 19 logs:This happens when a transition suspends on a lazy route component inside a Suspense boundary that is already showing content, the import resolves, and a second transition lands before React retries.
Your Example Website or App
https://github.com/alebedev/tanstack-lazy-use-repro
Steps to Reproduce the Bug or Issue
npm install && npm run devsrc/routes/index.tsxholds the import behind a gate so the timing is deterministic: a transition renders<Lazy />(it suspends), then the gate opens and a secondstartTransitionruns in the same tick.Expected behavior
No warning.
Lazyshould calluse()on every render that follows one where it suspended throughuse().Actual behavior
The error above is logged every time (3/3 runs in headless Chromium;
npm run checkin the repo automates it).Proposed fix
Keep the fulfilled promise on the client, and call
use()on it after it has resolved. React setstatus = 'fulfilled'when it tracked the thenable, so thisuse()returns synchronously and never suspends an already loaded component:loadPromise = importer() .then((res) => { if (!(isServer ?? typeof window === 'undefined')) { - loadPromise = undefined ;(lazyComp as any).preload = undefined } comp = res[exportName ?? 'default'] }) @@ } else { throw load() } + } else if (reactUse && (loadPromise as any)?.status === 'fulfilled') { + reactUse(loadPromise) }With this applied to
node_modules, the repro no longer warns and the component still renders. We've been running it as a local patch in production. Happy to open a PR.Platform