Replies: 2 comments 5 replies
-
Those are all valid points, and I think this is an intentional design decision by React Suspense. If you compare this to a server component, you'll have the same problem if you do:
maybe its more obvious because the syntax is async/await, but its the same problem. The react way to solve this is to split things up into multiple components (component composition). Even if they are in the same suspense boundary, fetches will start in parallel. If you don't want to do that, you can
I think the I also don't see how this example is much different:
Here, when cc @Ephem I know you like to prevent fetch waterfalls and you're currently writing the docs on suspense / SSR, so maybe there's something I'm missing here? |
Beta Was this translation helpful? Give feedback.
-
Is there any update to this? @Ephem Did you find a solution to your problem? I am facing the same bottleneck now. @SebKranz |
Beta Was this translation helpful? Give feedback.
-
The current api for suspense (
useSuspenseQuery
anduseSuspenseQueries
) makes waterfalls far too likely - especially when combined with custom hooks. In the original API, two tasks, initiating the fetch and reading the result, are done in the same call.This made a lot of sense when React required all hooks to be called unconditionally on every render.
However, with the introduction of suspense, this isn't guaranteed anymore. It is now far more likely that some fetches wont be initiated until others have finished. As a result, waterfalls become much more likely, and nearly every component that fetches multiple endpoints must require explicit consideration from the developer to prevent this.
While waterfalls can be avoided with
useQueries
or prefetching, it is much more difficult to work around when you want to extract logic into custom hooks.In the above example, theres no obvious way to execute both custom hooks at the same time. I could prefetch queries in advance, but then
CourseView
must have knowledge of all the query keys that my custom hooks will use.As a result, it is far more difficult to decouple logic and implement custom hooks independently of each other.
Further, since
useSuspenseQuery
anduseQuery
are different hooks, I can't simply configure my custom hook to use Suspense conditionally (useStudents({ withSuspense: false })
). Instead, I need to implement multiple versions:useStudents
anduseStudentsSuspending
.Alternative solution
I would suggest disconnecting the place where the fetch is initiated, from the place where the result is read.
Add a suspending function
.read()
toUseQueryResult
.This has the following advantages:
useQuery
without suspense.For example, I can imagine a design where a component extracts some data from the result, before passing it to a suspending component:
Beta Was this translation helpful? Give feedback.
All reactions