Async Cell
Generic component for displaying data by ID with automatic batched fetching
Live Example
Basic AsyncCell
Display project names by ID with automatic batching
Project 759: -
Project 760: -
Project 761: -
ℹ️ These 3 components result in ONE API call with id__in=759,760,761
Custom Rendering
Use a custom render function to display complex data
Unknown project
Specialized Components
Pre-built components for common use cases
Project: #759
Organization: #1
With Loading State
Show custom loading and fallback states
Loading...
Overview
The AsyncCell component is a generic utility for displaying data fetched asynchronously by ID. It uses intelligent batching to combine multiple requests into a single API call, making it perfect for table cells and other scenarios where you need to display related data by ID.
Features
- Automatic Batching: All AsyncCell components rendered within 50ms have their requests batched into a single API call using
id__in - Smart Caching: If the item is already in the collection, it returns immediately from cache without making an API call
- 50ms Debounce: Waits 50ms to collect all IDs before making the API call
- Type-Safe: Fully typed with TypeScript generics
- Flexible Rendering: Custom render function or automatic rendering of the
nameproperty
Usage
Basic Usage (Auto-renders name)
import { useSGERP } from 'sgerp-frontend-lib';
import { AsyncCell } from '@/components/sgerp/async-cell';
function MyComponent() {
const api = useSGERP();
return (
<AsyncCell
collection={api?.collections.project}
id={123}
/>
);
}
Custom Rendering
<AsyncCell
collection={api?.collections.vehicle}
id={vehicleId}
render={(vehicle) => (
<div>
<span>{vehicle.service_number}</span>
<span className="text-muted-foreground ml-2">({vehicle.color})</span>
</div>
)}
fallback={<span className="text-muted-foreground">Unknown vehicle</span>}
/>
In Table Columns
const columns: ColumnDef<Booking>[] = [
{
key: 'project_id',
label: 'Project',
render: (_, booking) => (
<AsyncCell
collection={api?.collections.project}
id={booking.project_id}
render={(project) => project.name}
/>
),
},
];
With Loading State
<AsyncCell
collection={api?.collections.passenger}
id={passengerId}
render={(passenger) => `${passenger.first_name} ${passenger.last_name}`}
loadingFallback={<span className="text-muted-foreground">Loading...</span>}
fallback={<span className="text-muted-foreground">Unknown</span>}
/>
Props
| Prop | Type | Required | Description |
|---|---|---|---|
collection | Collection<T> | Yes | The collection to fetch from |
id | number | string | Yes | The ID of the item to fetch |
render | (item: T) => ReactNode | No | Custom render function. Defaults to rendering the name property |
fallback | ReactNode | No | Content to show when item is not found. Default: '-' |
loadingFallback | ReactNode | No | Content to show while loading. If not provided, shows fallback |
How Batching Works
When multiple AsyncCell components are rendered:
- Each component requests its item by ID via
collection.getAsync(id) - Requests are queued for 50ms (debounced)
- After 50ms, all queued IDs are combined into a single API call:
?model=project&id__in=1,2,3,4,5 - Results are distributed to all waiting components
- Subsequent renders for the same ID use cached data (no API call)
Example:
// These 5 components will result in ONE API call:
// GET /api/v2/microservices/get?model=project&id__in=1,2,3,4,5
<AsyncCell collection={api?.collections.project} id={1} />
<AsyncCell collection={api?.collections.project} id={2} />
<AsyncCell collection={api?.collections.project} id={3} />
<AsyncCell collection={api?.collections.project} id={4} />
<AsyncCell collection={api?.collections.project} id={5} />
Specialized Components
The library includes pre-built AsyncCell wrappers for common use cases:
ProjectName
import { ProjectName } from '@/components/sgerp/project-name';
<ProjectName projectId={123} />
OrganizationName
import { OrganizationName } from '@/components/sgerp/organization-name';
<OrganizationName organizationId={456} />
Performance Tips
- Use in tables: Perfect for displaying related data in table columns
- Avoid unnecessary re-renders: Memoize your render function if it's complex
- Pre-fetch data: If you know you'll need certain items, consider pre-fetching them into the collection
- Cache benefits: Once an item is fetched, all subsequent renders use the cache
Related
- Collections - Understanding the Collection API
- SGERPTable - Using AsyncCell in tables