Error Handling
Learn how to handle errors effectively in qortex. Best practices for error states, retry logic, and fallback data.
Error Handling Patterns
Basic Error Handling
Handle errors with proper loading and error states
function TodosList() {
const { data, isLoading, error, refetch } = useQuery(["todos"]);
if (isLoading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
return (
<div>
<button onClick={() => refetch()}>Refresh</button>
<ul>
{data?.map(todo => (
<li key={todo.id}>{todo.title}</li>
))}
</ul>
</div>
);
}
Graceful Degradation
Show placeholder data while handling errors gracefully
function ProductList() {
const { data: products, error } = useQuery(["products"], {
placeholderData: [], // Show empty list while loading
usePlaceholderOnError: true // Show empty list on error
});
return (
<div>
{error && (
<div className="error-banner">
ā ļø Some products couldn't be loaded, showing cached data
</div>
)}
{products?.map(product => (
<ProductCard key={product.id} product={product} />
))}
</div>
);
}
Retry Logic
Implement retry logic with exponential backoff
function DataComponent() {
const [retryCount, setRetryCount] = useState(0);
const { data, error, refetch } = useQuery(["data"], {
enabled: retryCount < 3 // Stop retrying after 3 attempts
});
const handleRetry = async () => {
setRetryCount(prev => prev + 1);
await refetch();
};
if (error && retryCount < 3) {
return (
<div>
<p>ā Something went wrong: {error.message}</p>
<button onClick={handleRetry}>
š Try Again ({retryCount}/3)
</button>
</div>
);
}
return <div>{/* Your content */}</div>;
}
Fallback Data
Provide meaningful fallback data for better UX
function UserProfile({ userId }: { userId: string }) {
const { data: user } = useQuery(["user", userId], {
placeholderData: {
name: "Loading...",
avatar: "/default-avatar.png",
bio: "User information is being loaded..."
},
usePlaceholderOnError: true
});
return (
<div>
<img src={user.avatar} alt={user.name} />
<h2>{user.name}</h2>
<p>{user.bio}</p>
</div>
);
}
Best Practices
ā Do
- ⢠Always provide meaningful error messages
- ⢠Use placeholder data for better UX
- ⢠Implement retry logic with limits
- ⢠Show loading states during retries
- ⢠Log errors for debugging
- ⢠Handle network connectivity issues
ā Don't
- ⢠Show technical error messages to users
- ⢠Retry indefinitely without limits
- ⢠Ignore error states in UI
- ⢠Leave users without feedback
- ⢠Forget to handle edge cases
- ⢠Expose sensitive information in errors
Error Handling Configuration
Global Configuration
// Set global error handling defaults
setDefaultConfig({
usePreviousDataOnError: true, // Keep previous data on error
usePlaceholderOnError: false, // Don't use placeholder on error
staleTime: 5 * 60 * 1000, // 5 minutes stale time
});
// Per-query error handling
registerFetcher(["critical-data"], {
fetcher: async () => {
const response = await fetch("/api/critical-data");
if (!response.ok) throw new Error('Failed to fetch critical data');
return response.json();
},
placeholderData: { status: 'loading' },
usePlaceholderOnError: true // Override global setting
});
Ready to Handle Errors?
Now that you understand error handling patterns, explore more advanced features and configuration options.