T
TanStack6mo ago
exotic-emerald

Using useSuspenseQuery for paginated requests

Am I understanding correctly that useSuspenseQuery is not the preferred way to render paginated data because, when changing pages, it is harder to show a loading state due to the existing data from the previous page? Or am I missing something? I am changing pages through React Router search params from another component. Currently, page changes work, but there is no indication of a loading state as there is with the initial useSuspenseQuery fetching.
10 Replies
absent-sapphire
absent-sapphire6mo ago
status is always success the derived flags are set accordingly.
so these do not make sense to use:
isPending: boolean A derived boolean from the status variable above, provided for convenience. isSuccess: boolean A derived boolean from the status variable above, provided for convenience. isError: boolean A derived boolean from the status variable above, provided for convenience.
Can you try using isFetching to show the loading indicator?
exotic-emerald
exotic-emeraldOP6mo ago
The problem with isFetching is that it also triggers the loading indicator when the page is being refetched (e.g., when you focus on the tab again). This makes it difficult to know whether you're refetching the same page or navigating to a different one.
genetic-orange
genetic-orange6mo ago
We use a modified version of this hook: https://www.teemutaskula.com/blog/exploring-query-suspense It will suspend to your suspense boundary on first load but not subsequent loads. This allows us to show a small spinner that is localized to the change when we want but otherwise only show the initial suspense boundary fallback state initially.
Exploring using Suspense with React Query
Learn how I explored using Suspense with React Query and what issues I encountered and how I solved them.
exotic-emerald
exotic-emeraldOP6mo ago
Woah, that looks exactly like what I've been looking for. Thanks!
fascinating-indigo
fascinating-indigo6mo ago
careful with this tho: return { ...query, isSuspending }; https://tanstack.com/query/latest/docs/framework/react/guides/render-optimizations#tracked-properties
If you use object rest destructuring, you will disable this optimization.
const newQuery = query as typeof query & { isSuspending: boolean };
newQuery.isSuspending = query.isFetching && queryKey !== deferredQueryKey;

return newQuery;
const newQuery = query as typeof query & { isSuspending: boolean };
newQuery.isSuspending = query.isFetching && queryKey !== deferredQueryKey;

return newQuery;
I use this instead
exotic-emerald
exotic-emeraldOP6mo ago
You saved me a lot of time debugging, I think. Thank you!
ambitious-aqua
ambitious-aqua6mo ago
Hi everyone 👋 Happy to hear that my article was helpful and thanks for pointing out the issue with property tracking. I've updated the article to use the proposed solution by @ferretwithabéret If you guys have any other improvement ideas don't hesitate to share 😊
fascinating-indigo
fascinating-indigo6mo ago
Ngl, I was thinking about emailing you about it, glad you noticed this thread
ambitious-aqua
ambitious-aqua6mo ago
@514sid actually emailed me about it which is how I noticed this discussion 😄 So big thanks to Sid as well 🤝
fascinating-indigo
fascinating-indigo2mo ago
This seems to trigger react-compiler's eslint rules, at least in my RN project. Fixed it with
const newQuery = query as typeof query & { isSuspending: boolean };
Object.assign(newQuery, {
isSuspending: query.isFetching && queryKey !== deferredQueryKey,
});
const newQuery = query as typeof query & { isSuspending: boolean };
Object.assign(newQuery, {
isSuspending: query.isFetching && queryKey !== deferredQueryKey,
});

Did you find this page helpful?