const { data, isPending, error } = useQuery({ ... , throwOnError: true });
if (isPending) {
return <>Loading...</>;
}
// `data` can still be `undefined` here
// I also have to return or rethrow if `error` is truthy, but that's not possible since `throwOnError` is enabled
if (error) {
return <>Ooops!</>;
}
// Now `data` is guaranteed to be defined here
// Alternatively, I can call a TS assertion function, like `assertDefined(data)`, but I feel like I shouldn't have toWhen |
Replies: 1 comment
|
Short answer: Types: Runtime: the error isn't always thrown. In result.isError &&
!errorResetBoundary.isReset() &&
!result.isFetching &&
query && (... || shouldThrowError(throwOnError, [result.error, query]))So right after a What you want is const { data } = useSuspenseQuery({ queryKey, queryFn })
// data: TData, never undefinedLoading goes to the nearest If you'd rather stay on const { data, isPending, isError } = useQuery({ ..., throwOnError: true })
if (isPending) return <>Loading...</>
if (isError) return null // only reachable during a boundary reset/refetch
data // TData |
Short answer:
throwOnErroris a runtime flag. It doesn't change the return type, and the runtime doesn't strictly guarantee it either.Types:
useQueryreturns a union discriminated bystatus, andthrowOnErrorisn't part of that type. It can also be a function ((error, query) => boolean), so TS can't know statically whether an error will throw.Runtime: the error isn't always thrown. In
getHasError(react-query/src/errorBoundaryUtils.ts) the throw only happens when:So right after a
QueryErrorResetBoundary/ErrorBoundaryreset, your compone…