Working with Data
When working with data, you will mostly interact with the <DataSource />
component, which is responsible for handling and managing the data and passing it down to the <InfiniteTable />
component, which is the rendering engine for the DataGrid.
So we provide those two components (as named exports) inside @infinite-table/infinite-react
package:
<DataSource />
- our data-handling component<InfiniteTable />
- our virtualized component
The <DataSource/>
component is responsible for the data the management layer.
Note
Probably the most important prop for the <DataSource />
component is the idProperty
prop. It specifies the property of the data object that is used as a unique identifier for data rows/items.
<DataSource<DATA_TYPE>
idProperty="id"
data={[]} // or a Promise or function returning a Promise.
The <DataSource />
is a generic React TypeScript component that can be bound to an array of items of the generic type.
Note
In this documentation, we'll use DATA_TYPE
when referring to the generic type. Rarely, we'll use T
.
<DataSource<DATA_TYPE>>
<InfiniteTable<DATA_TYPE> />
</DataSource>
Most of our examples in these docs have a Developer
or Employee
TypeScript data type used as the generic type for the <DataSource />
component.
import { DataSource } from '@infinite-table/infinite-react';
type Employee = {
id: string | number;
name: string;
salary: number;
department: string;
company: string;
};
const employees: Employee[] = [
{ id: 1, name: 'Bob', salary: 10_000, department: 'IT', company: 'Bobsons' },
{
id: 2,
name: 'Alice',
salary: 20_000,
department: 'IT',
company: 'Bobsons',
},
{ id: 3, name: 'John', salary: 30_000, department: 'IT', company: 'Bobsons' },
];
<DataSource<Employee> primaryKey={'id'} data={employees}
In the snippet above, we see 3 important details:
- the component is bound to the
Employee
type - we use a
primaryKey
property - here it isid
, but since the bound type isEmployee
,primaryKey
iskeyof Employee
- we pass the
employees
array as thedata
property.
Note
The data
prop can be either:
- an array of the bound generic type - here
Employee[]
- a Promise tha resolves to an array like the above
- a function that returns any of the above
import { InfiniteTable, DataSource, InfiniteTableColumn, } from '@infinite-table/infinite-react'; import * as React from 'react'; type Employee = { id: string | number; name: string; salary: number; department: string; company: string; }; const employees: Employee[] = [ { id: 1, name: 'Bob', salary: 10_000, department: 'IT', company: 'Bobsons', }, { id: 2, name: 'Alice', salary: 20_000, department: 'IT', company: 'Bobsons', }, { id: 3, name: 'John', salary: 30_000, department: 'IT', company: 'Bobsons', }, { id: 4, name: 'Jane', salary: 35_000, department: 'Marketing', company: 'Janies', }, { id: 5, name: 'Mary', salary: 40_000, department: 'Marketing', company: 'Janies', }, ]; // simulate data-loading with a 1500ms delay const data = new Promise<Employee[]>((resolve) => { setTimeout(() => { resolve(employees); }, 1500); }); export default function App() { return ( <DataSource<Employee> data={data} primaryKey="id"> <InfiniteTable<Employee> columnDefaultWidth={130} columns={columns} /> </DataSource> ); } const columns: Record<string, InfiniteTableColumn<Employee>> = { id: { field: 'id', type: 'number', defaultWidth: 80, }, name: { field: 'name', }, salary: { field: 'salary', type: 'number' }, department: { field: 'department', header: 'Dep.' }, company: { field
Data Loading Strategies
We're aware there are countless strategies for loading data - each with its own strengths. We decided we should focus on building what we do best, namely building virtualized components, so we encourage you to use your preferred data-fetching library/solution. This being said, we still provide you with the flexibility you need when using the <DataSource/>
, so here's what you can use for the data
prop of the component:
- an array of the bound type
- a Promise that resolves to an array of the bound type
- a function that returns any of the above
While you're loading the data, you can always render a loading indicator - pass the loading
prop into the component (along with loadingText
prop in the <InfiniteTable />
component if you want to customize the message).
Using fetch
For basic datasets, which have simple data requirements, using fetch
is probably sufficient, so here is an example:
import { InfiniteTable, DataSource } from '@infinite-table/infinite-react'; import * as React from 'react'; import { columns, Employee } from './columns'; export default function App() { return ( <DataSource<Employee> data={dataSource} primaryKey="id"> <InfiniteTable<Employee> columns={columns} /> </DataSource> ); } const dataSource = () => { return fetch('https://infinite-table.com/.netlify/functions/json-server' + '/employees10k') .then((r) => r.json()) .then((data: Employee[]) => {
Re-fetching on change
It's important to note you can re-fetch data by changing the reference you pass as the data
prop to the <DataSource/>
component.
Note
Passing another data
function, will cause the component to re-execute the function and thus load new data.
Alternatively, you can use the refetchKey
prop to trigger a re-fetch - give it a new value (eg: use it as a counter, and increment it) and the component will re-fetch the data.
import { InfiniteTable, DataSource } from '@infinite-table/infinite-react'; import * as React from 'react'; import { columns, Employee } from './columns'; const getDataSourceFor = (size: string) => { if (size === '0') { return () => Promise.resolve([]); } return () => { return fetch('https://infinite-table.com/.netlify/functions/json-server' + '/employees' + size) .then((r) => r.json()) .then((data: Employee[]) => data); }; }; export default function App() { const [dataSourceSize, setDataSourceSize] = React.useState<string>('10'); const dataSource = React.useMemo(() => { return getDataSourceFor(dataSourceSize); }, [dataSourceSize]); return ( <div style={{ display: 'flex', flex: 1, color: 'var(--infinite-cell-color)', flexFlow: 'column', background: 'var(--infinite-background)', }} > <p style={{ padding: 10 }}>Please select the size of the datasource:</p> <div style={{ padding: 10 }}> <select style={{ margin: '10px 0', display: 'inline-block', background: 'var(--infinite-background)', color: 'currentColor', padding: 'var(--infinite-space-3)', }} value={dataSourceSize} onChange={(event) => { const newSize = event.target.value as string; setDataSourceSize(newSize); }} > <option value="0">no items</option> <option value="10">10 items</option> <option value="100">100 items</option> <option value="1k">1k items</option> <option value="10k">10k items</option> </select> </div> <DataSource<Employee> data={dataSource} primaryKey="id"> <InfiniteTable<Employee> columns={columns} columnDefaultWidth={150} /> </DataSource> </div>
Live Updates
You can update your data in real-time by using our DataSource API.
DataSource API
Read more about how to use our API to update your data in real-time