2021 December 10thHandling `undefined` in React Query and Typescriptreact-query, typescript,
useQuery
can return undefined because:
Generally, on the first render cycle, data will be
undefined
because well, the data is async and does not exist yet on the frontend. The component will render in theloading
state in this case with theisLoading
flag set totrue
. so that you can act accordingly.
So can use the isLoading
flag to act accordingly. However, things change a bit when you use either placeholderData
or initialData
. If you use either one, the query will not be in loading state, but go directly to success state.Wrt to undefined
, the difference between the two though is that with initialData
, data will never be undefined
. This is because if it errors, the query will be in error state, but your initial data will still be there. For placeholderData
, query will be in error state and data will be undefined
.1
Regardless though, one constant remains. The typescript types atm will always return a union with undefined
. In simpler terms... the return type of useQuery
will always be T | undefined
. placeholderData
nor initialData
do not narrow the type.
This means you will always need to handle for undefined
and the simplest way I've seen is to just use a nullish coalescing operator.
const { data } = useQuery("active-events", () => getEventsAsync());
const events = data ?? []
return (
events.map(event => `Some ${event}.`)
)
Non-null assertion is also possible, but then you'd have to assert whenever you call data
.
Another way to deal with undefined
is by using the object returned by useQuery
instead of destructuring. By doing so, Typescript can narrow the type when using the status field or one of the status booleans:
const { data, isSuccess } = useGroups()
if (isSuccess) {
// 🚨 data will still be `Group[] | undefined` here
}
const groupsQuery = useGroups()
if (groupsQuery.isSuccess) {
// ✅ groupsQuery.data will now be `Group[]`
}