Skeleton Caching
How Caching Works
UI States can cache generated skeleton structures in sessionStorage. This allows instant skeleton display on subsequent loads, even before your content renders for the first time.
Enable Caching
Enable caching with the enableCache and cacheKey props:
typescript
<UIStates data={data} loading={loading} enableCache={true} cacheKey="user-profile"> <div> <h1>{data.name}</h1> <p>{data.email}</p> </div></UIStates>Cache Key
The cacheKey should be unique per component/view. Use descriptive keys that reflect the content:
typescript
// Different cache keys for different views<UIStates cacheKey="user-profile" enableCache>...</UIStates><UIStates cacheKey="user-settings" enableCache>...</UIStates><UIStates cacheKey="product-list" enableCache>...</UIStates>
// Dynamic cache keys<UIStates cacheKey={`product-${productId}`} enableCache>...</UIStates>Cache Lifetime
Cached skeletons are stored in sessionStorage and automatically invalidated:
- After 5 minutes (time-based invalidation)
- When viewport width changes by more than 50px (responsive invalidation)
- When the browser session ends (sessionStorage clears)
Cache Flow
- First load: Default skeleton shown, then content renders
- Content renders: UI States measures DOM and saves to sessionStorage
- Subsequent loads: Cached skeleton shown instantly during loading
- Content renders: Real content replaces skeleton
Benefits
| Without Cache | With Cache |
|---|---|
| Generic skeleton on every load | Accurate skeleton instantly |
| Layout shift when content loads | Smooth transition, less CLS |
| Skeleton doesn't match content | Perfect match from cache |
Complete Example
typescript
function UserDashboard() { const query = useQuery({ queryKey: ["dashboard"], queryFn: fetchDashboard, });
return ( <UIStates query={query} enableCache={true} cacheKey="dashboard-main" > <div className="grid grid-cols-3 gap-4"> <StatsCard title="Users" value={query.data.users} /> <StatsCard title="Revenue" value={query.data.revenue} /> <StatsCard title="Orders" value={query.data.orders} /> </div>
<div className="mt-8"> <h2 className="text-xl font-bold">Recent Activity</h2> <ActivityList items={query.data.activity} /> </div> </UIStates> );}Caching is especially useful for complex layouts with many elements. The skeleton will perfectly match your grid, cards, and text elements from the first cached load.