Describe the bug
I have been playing around with v2 and v3 to experiment for a new project, and have noticed that the returned type for useQuery is incorrect with suspense.
I am beginning to think there should be an aliased function with different return types for suspense.
To Reproduce
useQueryconst { data } = useQuery<Todo[]>('todos', getTodos);
Todo[] | undefinedbut isn't that expected though? In the first render cycle, your status will be 'loading' so you have no data yet, thus data will be undefined. Only if your status goes to 'success', you will have data to use (at least this is how it is without suspense, not sure how suspense influences anything here).
Tagged unions discriminated by the status field were added in v3 - lots of discussions about that topic in this PR: https://github.com/tannerlinsley/react-query/pull/1108
and it was then done in this PR: https://github.com/tannerlinsley/react-query/pull/1247
Ah, you could be right. My understanding of suspense was that if the data isn't loaded, it "throws" a promise which bubbles up to the <Suspense /> and renders the fallback, and it wouldn't try rendering any of the data that isn't loaded yet.
Yeah when you use suspense, React Query throws an error while it's loading or if it failed, so the only case when it renders your component is when the request is already a success, so if your request can't return undefined the data will always be there.
I saw this same behavior in my app, I'm also using suspense, and I end up all the time adding a if (!data) return null before the render and at the beginning of each effect, memo or callback just to make TS don't think that data can be undefined, in practice, these conditions never work and data is never undefined.
ah okay, got it. so what we would need to do, on type level, is return T rather than T | undefined if the option suspense was set to true?
Yes, I should just read the docs I guess:
When using suspense mode, status states and error objects are not needed and are then replaced by usage of the React.Suspense component (including the use of the fallback prop and React error boundaries for catching errors)
@boschni is this doable on type level?
The only way to make this work is to create separate suspense hooks as the suspense option can be set globally. But I guess the data could still be undefined if enabled is set to false for example.
Yep 鈽濓笍
ah okay, got it. so what we would need to do, on type level, is return T rather than T | undefined if the option suspense was set to true?
@TkDodo I think this needs to be the signature when initialData is set as well, not just when suspense is set. See: https://github.com/tannerlinsley/react-query/discussions/1301
Most helpful comment
The only way to make this work is to create separate suspense hooks as the suspense option can be set globally. But I guess the data could still be undefined if
enabledis set to false for example.