TanStack Query Integration
Direct Query Support
UI States has built-in support for TanStack Query. Simply pass the query result directly:
typescript
import { UIStates } from "@promise-inc/ui-states";import { useQuery } from "@tanstack/react-query";
function UserProfile() { const query = useQuery({ queryKey: ["user"], queryFn: () => fetch("/api/user").then(res => res.json()), });
return ( <UIStates query={query}> <div> <h1>{query.data.name}</h1> <p>{query.data.email}</p> </div> </UIStates> );}Automatic State Detection
When you pass a query object, UI States automatically extracts:
- data from query.data
- loading from query.isLoading
- error from query.error
Refetch on Error
Error states automatically include a retry button that calls query.refetch():
typescript
const query = useQuery({ queryKey: ["user"], queryFn: fetchUser, retry: 3, // TanStack Query retry});
<UIStates query={query}> <div>{query.data.name}</div></UIStates>// Error state shows "Retry" button that calls query.refetch()Query with Caching
Combine TanStack Query with skeleton caching for optimal UX:
typescript
function UserList() { const query = useQuery({ queryKey: ["users"], queryFn: fetchUsers, });
return ( <UIStates query={query} enableCache={true} cacheKey="user-list" > {query.data.map(user => ( <div key={user.id}> <h2>{user.name}</h2> <p>{user.email}</p> </div> ))} </UIStates> );}Manual Props with Query
You can override automatic detection by passing manual props:
typescript
<UIStates query={query} loading={query.isLoading || query.isFetching} // Include background refetch data={query.data?.items} // Use nested data> {query.data.items.map(item => ( <div key={item.id}>{item.name}</div> ))}</UIStates>The query prop accepts any object with data, isLoading, and error properties, so it works with other data fetching libraries that follow a similar pattern.