Loading state
Pass isLoading: true to render skeleton rows and a progress bar in place of the data. Flip it back to false to reveal the real rows. This is especially useful with server-side data, where you toggle it around each fetch.
ID | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| Ava | Thompson | Owner | Engineering | active | 22 | $45,000 | Jan 2, 2023 | 0% | ||
| Liam | Nguyen | Admin | Marketing | inactive | 25 | $47,137 | Jan 13, 2023 | 9% | ||
| Noah | Silva | Editor | Design | pending | 28 | $49,274 | Jan 24, 2023 | 18% | ||
| Emma | Carter | Viewer | Sales | active | 31 | $51,411 | Feb 4, 2023 | 27% | ||
| Olivia | Rossi | Owner | Support | inactive | 34 | $53,548 | Feb 15, 2023 | 36% | ||
| William | Walker | Admin | Engineering | pending | 37 | $55,685 | Feb 26, 2023 | 45% | ||
| Sophia | Patel | Editor | Marketing | active | 40 | $57,822 | Mar 9, 2023 | 54% | ||
| James | Muller | Viewer | Design | inactive | 43 | $59,959 | Mar 20, 2023 | 63% | ||
| Isabella | Park | Owner | Sales | pending | 46 | $62,096 | Mar 31, 2023 | 72% | ||
| Lucas | Reyes | Admin | Support | active | 49 | $64,233 | Apr 11, 2023 | 81% | ||
| $4,120,536 |
Usage
Drive isLoading from your own state and toggle it however you like — here with useState and a button in renderToolbarActions:
const [isLoading, setIsLoading] = useState(false)
const table = useDataTable({
data,
columns,
getRowId: (row) => row.id,
isLoading,
renderToolbarActions: () => (
<Button
variant="outline"
size="sm"
onClick={() => setIsLoading((prev) => !prev)}
>
{isLoading ? "Show data" : "Show loading"}
</Button>
),
})
return <DataTable table={table} />
Reading the state
You can read the current value back from the table instance:
if (table.cnTable.isLoading) {
// skeletons + progress bar are showing
}
Pairs well with server-side data
Set isLoading to true before a request and back to false when it
resolves so users always see the skeletons while new pages or filtered results
load.
Saving state
For an in-flight mutation (rather than an initial load), set isSaving: true. It shows the progress bar without replacing rows with skeletons, so the current data stays visible while the save runs.
useDataTable({ data, columns, getRowId: (row) => row.id, isSaving })
Choosing which affordances show
isLoading turns on three affordances together; override any of them independently:
showProgressBars— the top progress bar (defaultisLoading || isSaving).showSkeletons— skeleton rows while the body is empty (defaultisLoading).showLoadingOverlay— a dimming overlay over existing rows (defaultisLoading).
useDataTable({
data,
columns,
getRowId: (row) => row.id,
isLoading,
showSkeletons: false, // keep rows visible, just dim + show the progress bar
})
Relevant options
| Prop | Type | Default | Description |
|---|---|---|---|
isLoading? | boolean | false | Show the loading affordances (progress bar; skeletons when empty; a dimming overlay over existing rows). Toggle each independently below. |
isSaving? | boolean | false | Show the progress bar for an in-flight save/mutation. Defaults the progress bar on without replacing rows with skeletons. |
showProgressBars? | boolean | — | Show the top progress bar. Default: `isLoading || isSaving`. |
showSkeletons? | boolean | — | Replace the body with skeleton rows while empty. Default: `isLoading`. |
showLoadingOverlay? | boolean | — | Dim existing rows with an overlay while loading. Default: `isLoading`. |