Replies: 1 comment
-
|
As an example where loaders are not a viable replacement to Suspense, I have a use case where state must be passed externally. Originally with the above code, I was passing this through This is not something that can be passed in the URL for the loader to access, as the data includes large files. |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Currently, react-router data mode doesn't allow for very good UX around pages that contain React Suspense usage.
Normally, when a React component suspends, the closest React.Suspense catcher handles the loading indication. However, this isn't quite the case if the trigger of the update happens to be wrapped in a startTransition() call. In such cases, React will defer loading the component entirely until the suspended function resolves its promise. Normally, for usages like this, React.useTransition returns a value indicating whether the transition is currently suspended, allowing components to re-render with UI indicating that the transition is pending.
However, the RouteProvider wraps navigation events in startTransition() by default, but does not provide a way to report to the site that a navigation is ongoing during the suspended time. Instead, the user is left staring at the same screen they were on as content loads. This provides for a very poor user experience whenever suspense is used on a page level.
Without the ability to get notified of pending transitions, the developer only has three options, none of which are ideal:
unstable_useTransitions={false}so react-router doesn't eat suspense calls, and use a React.Suspense in a LayoutContainerOf these, the first two don't allow for preserving the current screen, as it would be with typical startTransition() usages, leading to jarring UX. The last one requires rearchitecting everything around react-router's rigid view of per-page loaders and throws out all of the benefits of using Suspense in the first place.
In order to make using async data loading even easier, I think react-router should fully commit to using startTransition and expose the transition state to the site. Given the current API of react-router, I think the place this makes the most sense to surface is in the useNavigation hook. Currently, everything in this hook applies to both client and server side. However, since pages suspending and loading their data is still very much in the lifecycle of a navigation. The actual route change may have finished, but the navigation is in a very real sense still pending, as nothing has been shown to the user yet. And without react-router exposing the state of it's internal startTransition, it is not possible for the web developer to obtain information on whether the page has actually rendered at all.
I feel like a 'transitioning' state exposed through useNavigation would make the most sense. A second hook could be created for this, but in the interest of keeping the API surface small, folding it into useNavigation seems the best option. Additionally, given that the user is not able to see the page content until the transition completes, it may be desirable to do away with the optimistic state change, and even hold the URL back until the transition finishes.
Given that React seems to be going all-in on Suspense, it would be very nice to see react-router adopt that too in an official capacity. The flexibility to use them anywhere in the component tree make them much preferable to page-centric loaders. It may even be conceivable that, in the future, the loader system could be deprecated in favor of these altogether, presuming the preloading story gets worked out.
For reference, this was the solution I was using up until recently. This allows all page navigations to show a loading indicator, even if the async data being awaited is deeply nested in the component hierarchy of the loading page. Unfortunately, I am being forced to switch to data mode in order to use navigation blocking, so this is no longer an option.
Beta Was this translation helpful? Give feedback.
All reactions