TanStack / router

🤖 Fully typesafe Router for React (and friends) w/ built-in caching, 1st class search-param APIs, client-side cache integration and isomorphic rendering.
https://tanstack.com/router
MIT License
7.75k stars 562 forks source link

Intent-based loading prevents pendingComponent from showing. #2008

Closed ArmandRedgate closed 1 week ago

ArmandRedgate commented 1 month ago

Describe the bug

Since #1534 was fixed with #1907, I've found that the pendingComponent will not show if intent-based loading is enabled. The age blocks indefinitely until the dependencies are loaded.

This is better than the behaviour from before the fix, but still leaves something to be desired, and is not the behaviour I'd expect.

Your Example Website or App

https://stackblitz.com/edit/github-gh73by

In the above, see navigation to the About page, which does not show the specified pending component unless intent-based loading is off.

Steps to Reproduce the Bug or Issue

Make sure your project has intent-based loading enabled.

1) Load into some part of your UI that contains a link with lazy-loaded code behind it. 2) Slow down your connection speed using browser throttling tools. 3) Hover and immediately click on the link

You will see that you will remain on the current page and no pendingComponent will render, even after the default 1 second wait time. This could be several seconds for slower connections and results in a poor user experience as they wonder "did I really click that link?"

Expected behavior

I expect the pendingComponent to show after the default 1 second wait time, as it does when preloading is disabled.

Screenshots or Videos

No response

Platform

Additional context

No response

jude98 commented 1 month ago

Similar issue here. I have updated to version ^1.47.1. Now when I navigate to a page, it takes few seconds to mount even though the route gets updated, but its not showing any kind of loading states. My router setup is like:

const router = createRouter({
  context: {
    queryClient,
  },
  defaultNotFoundComponent: () => (
    <div>
      <p>Oops, not found!</p>
    </div>
  ),
  defaultPendingComponent: () => <Text>Loading...</Text>,
  // defaultPendingMs: 0,
  defaultPreload: 'intent',
  // defaultPreloadDelay: 0,
  routeTree,
});

I have nested routes

src/routes/~pool/~swap/~$tokenAddress.lazy.tsx file:

export const Route = createLazyFileRoute('/pool/swap/$tokenAddress')({
  component: () => (
      <Trade />
  ),
});

src/routes/~pool/~swap/~$tokenAddress.tsx file:

const Route = createFileRoute('/pool/swap/$tokenAddress')({
  validateSearch: (search: Record<string, unknown>): SwapSearchParams => ({
    in: (search.in as string) || '',
    out: (search.out as string) || '',
    pool: (search.pool as string) || '',
  }),
});

The loading state is only shown when the app first loads.

Any workaround for this?

MaciejGarncarski commented 3 weeks ago

I have same issue, it would be nice if I could add some loading indicator, because when user tries to navigate the app feels like frozen.

gregmsanderson commented 1 week ago

Ah ... that explains what I've been finding. Same problem.

I tried all of the options like defaultPreloadStaleTime: 0 and defaultStaleTime: Infinity etc. and whatever I did, my pending component would not show.I faked a delay in loader(), clicked that link ... and nothing happens. It looks frozen. No feedback. Couldn't figure it out.

But then I saw this issue and noticed I had defaultPreload: "intent". Sure enough, removed that ... and the pending component shows.

jude98 commented 1 week ago

Ah ... that explains what I've been finding. Same problem.

I tried all of the options like defaultPreloadStaleTime: 0 and defaultStaleTime: Infinity etc. and whatever I did, my pending component would not show.I faked a delay in loader(), clicked that link ... and nothing happens. It looks frozen. No feedback. Couldn't figure it out.

But then I saw this issue and noticed I had defaultPreload: "intent". Sure enough, removed that ... and the pending component shows.

@gregmsanderson Can you just give an example here for your solution? Maybe the route config.

gregmsanderson commented 1 week ago

@jude98 Ah, I haven't solved it. I just bypassed it.

My pending component was not showing with defaultPreload: "intent" in my router options. I just commented that line out. That's all I did. With that line commented out, I assume it defaults to not preload. So it is a bug with preload and the solution (for now) seems to be to not preload.