Skip to content

lazyRouteComponent skips use() after the import resolves, triggering React 19's "conditional use()" warning #8487

Description

@alebedev

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

  1. npm install && npm run dev
  2. Open http://localhost:3000 with the DevTools console open.
  3. 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)

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