@asphalt-react/data-table
v2.12.2
Published
Data Table
Readme
DataTable
DataTable component displays structured data in a tabular format with support for pagination. It provides an intuitive way to present large datasets with automatic or manual pagination controls. The component handles data validation, row identification, and responsive pagination controls including items per page selection.
DataTable supports two pagination modes: manual pagination where you manage the pagination state externally, and auto-pagination where the component automatically handles pagination internally using the provided data.
Usage
import React from "react"
import { DataTable } from "@asphalt-react/data-table"
const header = [
{ key: "email", value: "Email" },
{ key: "firstName", value: "First Name" },
{ key: "age", value: "Age" }
]
const data = [
{ uniqueId: "user-001", email: "[email protected]", firstName: "John", age: 28 },
{ uniqueId: "user-002", email: "[email protected]", firstName: "Jane", age: 32 },
{ uniqueId: "user-003", email: "[email protected]", firstName: "Bob", age: 45 }
]
function App() {
return (
<DataTable
header={header}
data={data}
identifier="uniqueId"
/>
)
}Data Structure
Header Configuration
The header prop defines the table columns:
const header = [
{ key: "email", value: "Email" },
{ key: "firstName", value: "First Name" },
{ key: "age", value: "Age" }
]Each header object requires:
key: Property name in the data objectsvalue: Display label for the column
Data Format
The data prop contains the table rows:
const data = [
{
uniqueId: "user-001",
email: "[email protected]",
firstName: "John",
age: 28
},
{
uniqueId: "user-002",
email: "[email protected]",
firstName: "Jane",
age: 32
}
]Requirements:
- Each object represents a table row
- Object keys should match header keys
- All objects must contain the identifier field
- Values can be strings, numbers, or React nodes
Hover
DataTable component accepts a hover prop to make it look highlighted when on hover.
Loading, Error, and Empty Data States
DataTable supports customizable states for loading, error, and empty data scenarios.
Loading State
Display a loading indicator while data is being fetched:
<DataTable
header={header}
data={data}
identifier="uniqueId"
loading={true}
/>Custom Loading Component
Provide a custom component for the loading state:
const CustomLoader = () => (
<div
style={{
display: "flex",
flexDirection: "column",
alignItems: "center",
justifyContent: "center",
padding: "10rem 0rem",
}}
>
<Loader size="large" />
<Text>Loading data...</Text>
</div>
)
<DataTable
header={header}
data={data}
identifier="uniqueId"
loading={true}
loadingComponent={CustomLoader}
/>Error State
Display an error message when data fetching fails:
<DataTable
header={header}
data={[]}
identifier="uniqueId"
error={true}
/>Custom Error Component
Provide a custom component for the error state:
const CustomError = () => (
<div
style={{
display: "flex",
flexDirection: "column",
alignItems: "center",
justifyContent: "center",
padding: "10rem 0rem",
}}
>
<Text>Failed to load data. Please try again.</Text>
<Button onClick={refetch}>Retry</Button>
</div>
)
<DataTable
header={header}
data={[]}
identifier="uniqueId"
error={true}
errorComponent={CustomError}
/>Empty State
DataTable will show a message if the data is empty automatically. Example use-case:
<DataTable
header={header}
data={[]}
identifier="uniqueId"
/>Custom Empty Component
Provide a custom component for the empty state:
const CustomEmpty = () => (
<div
style={{
display: "flex",
flexDirection: "column",
alignItems: "center",
justifyContent: "center",
padding: "10rem 0rem",
}}
>
<Text>No data available</Text>
</div>
)
<DataTable
header={header}
data={[]}
identifier="uniqueId"
emptyComponent={CustomEmpty}
/>Pagination Feature
DataTable supports two distinct pagination modes:
1. Auto-Pagination
When autoPaginate={true} is set, the DataTable automatically:
- Calculates total pages based on data length
- Manages internal pagination state
- Slices the data for the current page
- Handles page and per-page changes internally
This mode is ideal for client-side pagination of static datasets.
import React from "react"
import { DataTable } from "@asphalt-react/data-table"
function App() {
return (
<DataTable
header={header}
data={largeDataset}
identifier="uniqueId"
autoPaginate={true}
paginationLink={false}
/>
)
}2. Manual Pagination
When autoPaginate is false (default), you have full control:
- Provide pre-sliced data for the current page
- Manage pagination state externally
- Handle server-side pagination or complex data fetching
- Control the total pages and records count
This mode is ideal for server-side pagination or when you need custom pagination logic.
import React, { useState } from "react"
import { Link } from "gatsby" // or any other router like react-router
import { DataTable, usePagination } from "@asphalt-react/data-table"
function App() {
const [currentPage, setCurrentPage] = useState(1)
const [currentPerPage, setCurrentPerPage] = useState(10)
const handlePaginationChange = ({ event, page, record }) => {
event.preventDefault()
if (page && page !== currentPage) {
setCurrentPage(page)
}
if (record && record !== currentPerPage) {
setCurrentPerPage(record)
setCurrentPage(1)
}
}
const handleTileProps = ({ page, record }) => ({
to: `?page=${page}&perPage=${record}`,
})
const { getPaginationProps, getSlicedData } = usePagination({
activePage: currentPage,
activePerPage: currentPerPage,
onChange: handlePaginationChange,
getTileProps: handleTileProps,
data: tableData,
as: Link,
link: true,
})
const currentData = getSlicedData(tableData)
return (
<DataTable
header={tableHeader}
data={currentData}
identifier="uniqueID"
{...getPaginationProps()}
/>
)
}Accessibility
- Use tab or shift+tab to navigate among pages.
Custom Link Components
Use router link components for client-side navigation:
import { Link } from "gatsby" // or any other router like react-router
import { DataTable, usePagination } from "@asphalt-react/data-table"
const handleTileProps = ({ page, record }) => ({
to: `?page=${page}&perPage=${record}`,
})
const { getPaginationProps } = usePagination({
activePage: currentPage,
activePerPage: currentPerPage,
getTileProps: handleTileProps,
as: Link,
link: true,
})
<DataTable
// ... other props
{...getPaginationProps()}
/>Hooks
usePagination
Internal hook that provides unified pagination event handlers and prop getters for DataTable components. This hook normalizes the interaction between pagination controls and per-page controls, ensuring consistent event handling across both auto and manual pagination modes.
Returns:
An object with:
getPaginationProps: Object containing all pagination state and handlers to spread onto DataTableactivePage: Current active page numberactivePerPage: Current items per page counttotalPages: Total number of pagestotalRecords: Total number of recordspaginationLink: Whether pagination items render as linkspaginationElement: Element type for pagination itemsonPaginationChange: Unified handler for both page and per-page changesgetTileProps: Unified prop getter for pagination tiles
getSlicedData: Function that slices data array to return only current page items
Parameters
const { getPaginationProps, getSlicedData } = usePagination({
activePage: 1, // Currently active page number
activePerPage: 25, // Current items per page count
data: myData, // Data array to calculate totals from
totalPages: 10, // Optional: Override calculated total pages
totalRecords: 250, // Optional: Override calculated total records
as: Link, // Custom element/component for pagination items
link: true, // Whether pagination items render as links
onChange: ({ event, page, record }) => {
// Unified change handler for both page and per-page changes
console.log('Event:', event, 'Page:', page, 'Record:', record);
},
getTileProps: ({ page, record }) => ({
to: `/users?page=${page}&perPage=${record}`,
'data-testid': `tile-${page}-${record}`
})
});Key Features
- Unified Event Handling: Both page navigation and per-page selection changes call the same
onChangecallback with consistent parameters{ event, page, record } - Prop Getters: Returns specialized prop getter functions that inject proper page/record context based on the control type
- Centralized Props:
getPaginationProps()returns all pagination state and handlers in a single object for easy spreading onto DataTable - Link Integration: Supports custom link components through
asparameter and thegetTilePropsfunction - Flexible Totals: Can calculate totals from data array or accept explicit
totalPagesandtotalRecordsfor server-side pagination - State Normalization: Ensures consistent state management between auto and manual pagination modes
Usage
const [currentPage, setCurrentPage] = useState(1)
const [currentPerPage, setCurrentPerPage] = useState(10)
const handlePaginationChange = ({ event, page, record }) => {
event.preventDefault()
if (page && page !== currentPage) {
setCurrentPage(page)
}
if (record && record !== currentPerPage) {
setCurrentPerPage(record)
setCurrentPage(1)
}
}
const { getPaginationProps, getSlicedData } = usePagination({
activePage: currentPage,
activePerPage: currentPerPage,
onChange: handlePaginationChange,
data: tableData,
link: false,
})
const currentData = getSlicedData(tableData)
return (
<DataTable
header={tableHeader}
data={currentData}
identifier="uniqueID"
{...getPaginationProps()}
/>
)Props
header
Data table header configuration.
Example:
[
{
key: "email",
value: "Email",
},
{
key: "firstName",
value: "First Name",
},
{
key: "age",
value: "Age",
}
]Each header object must contain:
- key: string identifier matching data object properties
- value: string display label for the column header
| type | required | default | | ------- | -------- | ------- | | arrayOf | true | N/A |
identifier
Field name in each data row used as the unique row identifier. This property name must exist in every data object and contain unique values for proper row identification and React key generation.
Example:
identifier="uniqueId"
// With data like:
[
{
uniqueId: "user-001",
name: "John",
email: "[email protected]"
},
{
uniqueId: "user-002",
name: "Jane",
email: "[email protected]"
}
]| type | required | default | | ------ | -------- | ------- | | string | true | N/A |
data
Table data rows to be displayed. Each object represents a row, with keys matching the header configuration. Property names should correspond to header.key values for proper column mapping.
Example:
[
{
uniqueId: "user-001",
email: "[email protected]",
firstName: "John",
age: 28
},
{
uniqueId: "user-002",
email: "[email protected]",
firstName: "Jane",
age: 32
},
{
uniqueId: "user-003",
email: "[email protected]",
firstName: "Bob",
age: 45
}
]Each data object should contain properties that match the keys defined in the header configuration. Values can be strings, numbers, or React nodes for custom cell content.
| type | required | default | | ------- | -------- | ------- | | arrayOf | true | N/A |
autoPaginate
Enable auto pagination logic.
| type | required | default | | ---- | -------- | ------- | | bool | false | false |
hover
Makes the row highlight on hover.
| type | required | default | | ---- | -------- | ------- | | bool | false | false |
loading
Whether the table is in a loading state. When true, a loading component will be displayed.
| type | required | default | | ---- | -------- | ------- | | bool | false | false |
loadingComponent
HTML element or React component to replace default loading display component.
| type | required | default | | ----------- | -------- | ------- | | elementType | false | N/A |
error
Whether the table is in an error state. When true, an error component will be displayed.
| type | required | default | | ---- | -------- | ------- | | bool | false | false |
errorComponent
HTML element or React component to replace default error display component.
| type | required | default | | ----------- | -------- | ------- | | elementType | false | N/A |
emptyComponent
HTML element or React component to replace default empty state display component.
| type | required | default | | ----------- | -------- | ------- | | elementType | false | N/A |
activePage
Current active page number for pagination. Used with pagination to control the currently displayed page.
| type | required | default | | ------ | -------- | ------- | | number | false | 1 |
activePerPage
Number of records to display per page. Controls how many table rows are shown on each page.
| type | required | default | | ------ | -------- | ------- | | number | false | 10 |
totalRecords
Total number of records in the dataset. Used to calculate pagination information and display record counts.
| type | required | default | | ------ | -------- | ------- | | number | false | N/A |
totalPages
Total number of pages available. Used by pagination component to render page navigation.
| type | required | default | | ------ | -------- | ------- | | number | false | N/A |
onPaginationChange
Callback function triggered when page or per-page selection changes.
Receives an object with:
- event: browser event
- page: new active page number
- record: new per-page value
| type | required | default | | ---- | -------- | ------- | | func | false | N/A |
paginationElement
HTML element or React component to replace default pagination elements. Useful for integrating with routing libraries like react-router-dom's Link.
| type | required | default | | ----------- | -------- | ------- | | elementType | false | "a" |
paginationLink
Whether pagination tiles should render as links. When true, pagination items will be rendered as anchor elements.
| type | required | default | | ---- | -------- | ------- | | bool | false | true |
getTileProps
Function to generate additional props for pagination tiles. Used to add custom attributes like href, id, data-attributes, etc.
Receives an object with:
- page: new active page number
- record: new per-page value
| type | required | default | | ---- | -------- | ------- | | func | false | N/A |
