Data in memory
ArraySource is a TableSource over JavaScript arrays. It does everything the grid asks for: sorting,
filters, search, find, column statistics, value lists and the summary of the selection.
import { ArraySource, DataGrid } from "vastgrid";import "vastgrid/styles.css";
const source = new ArraySource({ columns: ["name", "born", "field"], rows: [ ["Ada Lovelace", 1815, "Mathematics"], ["Grace Hopper", 1906, "Computer science"], ],});
<div style={{ height: 400 }}> <DataGrid source={source} /></div>;Rows or columns
Section titled “Rows or columns”Give the data row by row in rows, or column by column in columnData, one array per column:
const source = new ArraySource({ columns: ["name", "born", "field"], columnData: [ ["Ada Lovelace", "Grace Hopper"], [1815, 1906], ["Mathematics", "Computer science"], ],});columnData is used as it is, without a copy, so it is the cheaper choice for large tables. Missing
values at the end of a short row or column are blank.
Values and types
Section titled “Values and types”A value is a CellValue: string | number | boolean | null. null is a blank cell.
With column names only, ArraySource infers each column’s type from its first 10,000 values: integer,
float, boolean, or string for everything else. Give a ColumnSchema to set the type yourself:
const source = new ArraySource({ columns: [ { name: "order_id", type: "integer" }, { name: "ordered_at", type: "timestamp" }, { name: "total", type: "decimal", sourceType: "DECIMAL(12,2)" }, { name: "paid", type: "boolean" }, ], rows: [[100001, "2024-01-01 09:12:44", "19800.00", true]],});The type decides how values are aligned, formatted, sorted and summed:
- Numbers (
integer,bigint,float,decimal) are right-aligned, grouped by the locale and summed in the selection. Give values that a JavaScript number cannot hold exactly, such as 64-bit integers beyond 2^53 or decimals that must keep their digits, as strings:"9007199254740993","19800.00". They sort and filter by their exact value. - Dates and times (
date,time,timestamp,timestamptz) are strings in ISO form (2024-01-31,2024-01-31 12:34:56), which sort correctly as text. - Booleans show as
TRUEandFALSE. - The
sourceTypeis shown in the column’s statistics, as the engine’s own name for the type.
The demo’s table of orders uses each of these.
How large
Section titled “How large”ArraySource sorts, filters and computes statistics on the main thread, and the page does not respond
while it does. It suits up to a few hundred thousand rows. A table of 300,000 rows and 13 columns, on an
Apple M2 Pro in Node.js 24:
| Operation | Time |
|---|---|
| Sort by a decimal column | 0.55 s |
| Sort by a text column | 0.15 s |
| Search all columns | 0.13 s |
| Column statistics | 0.15 s |
Scrolling and selecting cost the same at any size: the grid reads only the rows on screen. For more rows,
serve files with vastgrid-duckdb, or move the work into a worker with a
TableSource of your own.
When the data changes
Section titled “When the data changes”A source is a snapshot. When the data changes, create a new ArraySource; the grid starts again with
it, so the selection, sort and filters are reset. To keep the sort and filters, save the query and apply
it to the new grid:
const grid = useRef<DataGridHandle>(null);const query = useRef<ViewQuery>({});const source = useMemo(() => new ArraySource({ columns, rows }), [rows]);
useEffect(() => { grid.current?.setQuery(query.current);}, [source]);
<DataGrid ref={grid} source={source} onQueryChange={(next) => (query.current = next)} />;