Files
dotfiles/dot_agents/skills/tanstack-query-best-practices/rules/err-error-boundaries.md
T
Prad Nukala 6406208b35 shell: fish functions -> ~/.local/bin executables + bash/zsh ports; manage ~/.agents
- 16 cross-shell utilities converted to sh/bash chezmoi executables:
  ai c2p cp-appid extract_agents fab gdc gh-sonr-org-migrate ghg-clone
  ghn gho git-summary launch_omp_livediff_overlay lc-elir mdcp mdp pj
  (ghg-clone not named ghg: unrelated cargo binary owns that name)
- cwd/history helpers stay per-shell: yy c cd clip-last + ghg/ghn/gho
  cd-wrappers in bash/functions/ and zsh/functions/, loaded by rc files
- fish keeps only shell-state functions; converted ones now hit PATH
- cp-appid ignore gating moved to .local/bin path
- dot_agents/skills: 82 skills materialized from dotstate storage so
  dot_claude skill symlinks resolve on fresh bootstrap; dotstate
  profile/symlinks.json released .agents/skills .bashrc .zshrc
2026-08-10 15:15:06 -04:00

151 lines
3.6 KiB
Markdown

# err-error-boundaries: Use Error Boundaries with useQueryErrorResetBoundary
## Priority: HIGH
## Explanation
When using Suspense with TanStack Query, errors propagate to error boundaries. Use `useQueryErrorResetBoundary` to reset query errors when users retry, preventing stuck error states.
## Bad Example
```tsx
// Error boundary without query reset - retry may not work
function ErrorBoundary({ children }: { children: React.ReactNode }) {
return (
<ReactErrorBoundary
fallbackRender={({ error, resetErrorBoundary }) => (
<div>
<p>Error: {error.message}</p>
<button onClick={resetErrorBoundary}>Try again</button>
{/* resetErrorBoundary alone doesn't reset query state */}
</div>
)}
>
{children}
</ReactErrorBoundary>
)
}
// Query error persists after retry click
```
## Good Example
```tsx
import { useQueryErrorResetBoundary } from '@tanstack/react-query'
import { ErrorBoundary } from 'react-error-boundary'
function QueryErrorBoundary({ children }: { children: React.ReactNode }) {
const { reset } = useQueryErrorResetBoundary()
return (
<ErrorBoundary
onReset={reset}
fallbackRender={({ error, resetErrorBoundary }) => (
<div className="error-container">
<h2>Something went wrong</h2>
<pre>{error.message}</pre>
<button onClick={resetErrorBoundary}>
Try again
</button>
</div>
)}
>
{children}
</ErrorBoundary>
)
}
// Usage with Suspense
function App() {
return (
<QueryErrorBoundary>
<Suspense fallback={<Loading />}>
<Posts />
</Suspense>
</QueryErrorBoundary>
)
}
function Posts() {
// useSuspenseQuery throws on error, caught by boundary
const { data } = useSuspenseQuery({
queryKey: ['posts'],
queryFn: fetchPosts,
})
return <PostList posts={data} />
}
```
## Good Example: With TanStack Router
```tsx
// Route-level error handling
import { createFileRoute } from '@tanstack/react-router'
import { useQueryErrorResetBoundary } from '@tanstack/react-query'
export const Route = createFileRoute('/posts')({
loader: ({ context: { queryClient } }) =>
queryClient.ensureQueryData(postQueries.list()),
errorComponent: ({ error, reset }) => {
const { reset: resetQuery } = useQueryErrorResetBoundary()
return (
<div>
<p>Failed to load posts: {error.message}</p>
<button
onClick={() => {
resetQuery()
reset()
}}
>
Retry
</button>
</div>
)
},
component: PostsPage,
})
```
## Error Boundary Placement Strategy
```tsx
// Granular error boundaries for isolated failures
function Dashboard() {
return (
<div className="dashboard">
{/* Each section can fail independently */}
<QueryErrorBoundary>
<Suspense fallback={<Skeleton />}>
<RecentActivity />
</Suspense>
</QueryErrorBoundary>
<QueryErrorBoundary>
<Suspense fallback={<Skeleton />}>
<Statistics />
</Suspense>
</QueryErrorBoundary>
<QueryErrorBoundary>
<Suspense fallback={<Skeleton />}>
<Notifications />
</Suspense>
</QueryErrorBoundary>
</div>
)
}
```
## Context
- `useQueryErrorResetBoundary` clears error state for all queries in the boundary
- Always pair Suspense queries with error boundaries
- Place boundaries based on failure isolation needs
- Consider inline error handling for non-critical data
- The reset only affects queries that were in error state