SuperAPI AI Directory

tanstack-query-intent-framework-handle-status-and-errors

Design & creation

View repository

Updated 10-16 00:02

About this skill

Core Patterns

Prefer data-first rendering when stale data is useful. A failed background refetch can produce isError while data is still available.

const todos = useQuery({ queryKey: ['todos'], queryFn: fetchTodos })

if (todos.data)
  return <TodoList todos={todos.data} isRefreshing={todos.isFetching} />
if (todos.isPending) return <Spinner />
if (todos.isError) return <ErrorMessage error={todos.error} />
return null

Use throwOnError when render-time Error Boundaries should own the fallback:

useQuery({
  queryKey: ['todos'],
  queryFn: fetchTodos,
  throwOnError: (error) => error.status >= 500,
})

Use global cache callbacks for cross-cutting notifications:

import { QueryCache, QueryClient } from '@tanstack/react-query'

const queryClient = new QueryClient({
  queryCache: new QueryCache({
    onError: (error, query) => {
      if (query.state.data !== undefined) showToast(error.message)
    },
  }),
})

Common Mistakes

HIGH Hiding stale data on background error

Wrong:

if (query.isError) return <ErrorMessage error={query.error} />
if (query.data) return <Todos todos={query.data} />

Correct:

if (query.data)
  return (
    <Todos todos={query.data} staleError={query.isError ? query.error : null} />
  )
if (query.isError) return <ErrorMessage error={query.error} />

Background refetch failures should not necessarily erase already-rendered data.

Source: https://tkdodo.eu/blog/status-checks-in-react-query

HIGH Sending validation errors to a global boundary

Wrong:

useMutation({ mutationFn: submitForm, throwOnError: true })

Correct:

useMutation({
  mutationFn: submitForm,
  throwOnError: (error) => error.status >= 500,
})

Handle expected 4xx validation errors near the form. Send unexpected server failures to the boundary.

Source: https://tkdodo.eu/blog/react-query-error-handling

MEDIUM Duplicating toast notifications per observer

Wrong:

useQuery({
  queryKey: ['todos'],
  queryFn: fetchTodos,
  onError: toastError,
})

Correct:

new QueryClient({
  queryCache: new QueryCache({
    onError: (error, query) => {
      if (query.state.data !== undefined) toastError(error)
    },
  }),
})

Observer-level callbacks can duplicate notifications across components. Use cache-level callbacks for global side effects.

Source: https://tkdodo.eu/blog/react-query-error-handling