gp-grid-logo
API Reference

Data Sources

Client-side and server-side data handling

Data Sources

gp-grid provides a flexible data source abstraction for both client-side and server-side data handling.

Basic Usage with rowData

The simplest approach is using the rowData prop directly:

const data = [
  { id: 1, name: "Giovanni" },
  { id: 2, name: "Luca" },
];

<Grid columns={columns} rowData={data} rowHeight={36} />

This internally creates a client data source.

Client Data Source

For more control, use createClientDataSource:

import { Grid, createClientDataSource } from "gp-grid-react";

const data = generateLargeDataset(1000000);
const dataSource = createClientDataSource(data);

<Grid columns={columns} dataSource={dataSource} rowHeight={36} />

Options

interface ClientDataSourceOptions<TData> {
  getFieldValue?: (row: TData, field: string) => CellValue;
  useWorker?: boolean;
}
OptionDefaultDescription
getFieldValue-Custom accessor for nested properties
useWorkertrueUse Web Worker for sorting large datasets

Nested Properties

const data = [
  { id: 1, user: { name: "Giovanni", email: "g@example.com" } },
];

const dataSource = createClientDataSource(data, {
  getFieldValue: (row, field) => {
    if (field === "userName") return row.user.name;
    if (field === "userEmail") return row.user.email;
    return row[field as keyof typeof row];
  },
});

Mutable Data Source

For CRUD operations and real-time data updates, use createMutableClientDataSource. This data source is backed by a robust transaction system that enables efficient batching and optimistic updates.

import { createMutableClientDataSource } from "gp-grid-react";

const dataSource = createMutableClientDataSource(data, {
  getRowId: (row) => row.id,  // Required: unique ID accessor
  debounceMs: 50,             // Batch updates (default: 50)
});

// Add rows
dataSource.addRows([{ id: 3, name: "Mario" }]);

// Remove rows
dataSource.removeRows([1, 2]);

// Update a cell
dataSource.updateCell(3, "name", "Maria");

// Update a row
dataSource.updateRow(3, { name: "Maria", email: "maria@example.com" });

// Force immediate processing
await dataSource.flushTransactions();

Transaction System

The mutable data source uses an internal transaction system that provides several key benefits:

Automatic Batching - Multiple operations within the debounce window are combined into a single transaction, minimizing re-renders and improving performance.

Optimistic Processing - Changes are queued and processed asynchronously, allowing the UI to remain responsive during bulk operations.

Transaction Callbacks - Track when transactions are processed:

const dataSource = createMutableClientDataSource(data, {
  getRowId: (row) => row.id,
  debounceMs: 50,
  onTransactionProcessed: (result) => {
    console.log(`Added: ${result.added}, Removed: ${result.removed}`);
    // Update external state, analytics, etc.
  },
});

Flush Control - Force immediate processing when needed:

// Wait for all pending transactions
await dataSource.flushTransactions();

// Check if there are pending changes
if (dataSource.hasPendingTransactions()) {
  // Handle pending state
}

Options

interface MutableClientDataSourceOptions<TData> {
  getRowId: (row: TData) => RowId;     // Required: unique ID accessor
  debounceMs?: number;                  // Batch window (default: 50)
  getFieldValue?: (row: TData, field: string) => CellValue;
  onTransactionProcessed?: (result: TransactionResult) => void;
}

interface TransactionResult {
  added: number;    // Count of rows added
  removed: number;  // Count of rows removed
  updated: number;  // Count of rows updated
}

MutableDataSource Interface

interface MutableDataSource<TData> extends DataSource<TData> {
  addRows(rows: TData[]): void;
  removeRows(ids: RowId[]): void;
  updateCell(id: RowId, field: string, value: CellValue): void;
  updateRow(id: RowId, data: Partial<TData>): void;
  flushTransactions(): Promise<void>;
  hasPendingTransactions(): boolean;
  getDistinctValues(field: string): CellValue[];
  getRowById(id: RowId): TData | undefined;
  getTotalRowCount(): number;
  subscribe(listener: DataChangeListener): () => void;
}

Use Cases

The mutable data source is ideal for:

  • Real-time dashboards - Live data feeds with frequent updates
  • Streaming data - WebSocket or SSE data streams
  • User editing - Forms and inline editing with immediate feedback
  • Bulk operations - Import, batch updates, mass delete

See the Live Data example for a complete implementation.

Server Data Source

For server-side sorting, filtering, and pagination:

import { createServerDataSource } from "gp-grid-react";

const dataSource = createServerDataSource(async (request) => {
  const { pagination, sort, filter } = request;

  const response = await fetch("/api/data", {
    method: "POST",
    body: JSON.stringify({
      page: pagination.pageIndex,
      pageSize: pagination.pageSize,
      sortBy: sort,
      filters: filter,
    }),
  });

  const result = await response.json();

  return {
    rows: result.data,
    totalRows: result.total,
  };
});

<Grid columns={columns} dataSource={dataSource} rowHeight={36} />

Request Interface

interface DataSourceRequest {
  pagination: {
    pageIndex: number;
    pageSize: number;
  };
  sort?: SortModel[];
  filter?: FilterModel;
}

Response Interface

interface DataSourceResponse<TData> {
  rows: TData[];
  totalRows: number;
}

Choosing a Data Source

ScenarioRecommended
Small dataset (under 10k rows)rowData prop
Large dataset, client-sidecreateClientDataSource
Editable data with CRUDcreateMutableClientDataSource
Server-side operationscreateServerDataSource

On this page