Working with Data

We’ve decoupled our data handling from our rendering engine by providing 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.

It is a generic TypeScript component that can be bound to an array of items of the generic type.

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:

  1. the component is bound to the Employee type
  2. we use a primaryKey property - here it is id, but since the bound type is Employee, primaryKey is keyof Employee
  3. we pass the employees array as the data property.

The data prop is probably the most important part, and it can be one of:

  • an array of the bound type - here Employee[]
  • a Promise tha resolves to an array like the above
  • a function that returns an any of the above
Data loading example with promise
View Mode
Fork
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 500ms delay
const data = new Promise<Employee[]>((resolve) => {
  setTimeout(() => {
    resolve(employees);
  }, 1000);
});

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.

So we decided we should focus on building what we do best, namely building virtualized components.

And we encourage you to use your preferred data-fetching library/solution and pass a dumb array of data to the <DataSource/> component.

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:

Using fetch for remote data
View Mode
Fork
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.

Re-fetching data
View Mode
Fork
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