Integration Guide
This guide covers adding GridStorm to your existing project, loading data from APIs, handling large datasets, and configuring TypeScript. Whether you use React with Vite, Next.js, or vanilla TypeScript, the setup follows the same pattern: create a grid engine, mount a renderer, and optionally add plugins.
React with Vite
pnpm add @gridstorm/core @gridstorm/dom-renderer @gridstorm/react @gridstorm/theme-default
import { GridStorm } from '@gridstorm/react';
import '@gridstorm/theme-default/styles.css';
const columns = [
{ field: 'name', headerName: 'Name', sortable: true, filter: true },
{ field: 'email', headerName: 'Email', flex: 1 },
{ field: 'revenue', headerName: 'Revenue', type: 'number' },
];
const rowData = [
{ name: 'Alice', email: 'alice@example.com', revenue: 50000 },
{ name: 'Bob', email: 'bob@example.com', revenue: 75000 },
];
export default function App() {
return (
<GridStorm
columns={columns}
rowData={rowData}
height={600}
width="100%"
onGridReady={(api) => console.log('Grid ready', api)}
/>
);
}
React with Next.js
GridStorm's DOM renderer requires browser APIs. Use dynamic imports to prevent SSR errors.
'use client';
import { GridStorm } from '@gridstorm/react';
import '@gridstorm/theme-default/styles.css';
export function DataGrid({ columns, rowData }) {
return (
<GridStorm
columns={columns}
rowData={rowData}
height={600}
/>
);
}
import dynamic from 'next/dynamic';
const DataGrid = dynamic(() =>
import('../components/DataGrid').then(m => ({ default: m.DataGrid })),
{ ssr: false }
);
export default function Page() {
return <DataGrid columns={columns} rowData={rowData} />;
}
React with Create React App
pnpm add @gridstorm/core @gridstorm/dom-renderer @gridstorm/react @gridstorm/theme-default
The setup is the same as Vite. Import the theme CSS at the top of your entry file:
import '@gridstorm/theme-default/styles.css';
Vanilla TypeScript
You can use GridStorm without React by creating the engine and renderer directly.
pnpm add @gridstorm/core @gridstorm/dom-renderer @gridstorm/theme-default
import { createGrid } from '@gridstorm/core';
import { DomRenderer } from '@gridstorm/dom-renderer';
import '@gridstorm/theme-default/styles.css';
const engine = createGrid({
columns: [
{ field: 'name', headerName: 'Name', sortable: true },
{ field: 'price', headerName: 'Price', type: 'number' },
],
rowData: [
{ name: 'Widget', price: 29.99 },
{ name: 'Gadget', price: 49.99 },
],
});
const renderer = new DomRenderer({
container: document.getElementById('grid')!,
engine,
});
renderer.mount();
<div id="grid" style="height: 400px; width: 100%;"></div>
Bundle Size and Tree-Shaking
GridStorm is designed for tree-shaking. Each plugin is a separate package, so you only pay for what you import.
// Full import -- pulls in everything
import { createGrid, SortingPlugin, FilteringPlugin } from '@gridstorm/core';
// Tree-shakeable -- import plugins individually
import { createGrid } from '@gridstorm/core';
import { createSortingPlugin } from '@gridstorm/plugin-sorting';
import { createFilteringPlugin } from '@gridstorm/plugin-filtering';
const engine = createGrid({
columns,
rowData,
plugins: [
createSortingPlugin(),
createFilteringPlugin(),
],
});
Approximate package sizes (minified + gzipped):
| Package | Size |
|---|---|
@gridstorm/core |
~12 KB |
@gridstorm/dom-renderer |
~8 KB |
@gridstorm/react |
~4 KB |
@gridstorm/theme-default |
~3 KB |
| Each plugin | ~1-3 KB |
Loading Data from REST APIs
import { useState, useEffect } from 'react';
import { GridStorm } from '@gridstorm/react';
function OrdersGrid() {
const [rowData, setRowData] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetch('/api/orders')
.then(res => res.json())
.then(data => {
setRowData(data);
setLoading(false);
});
}, []);
if (loading) return <div>Loading...</div>;
return (
<GridStorm
columns={[
{ field: 'orderId', headerName: 'Order ID' },
{ field: 'customer', headerName: 'Customer' },
{ field: 'total', headerName: 'Total', type: 'number' },
]}
rowData={rowData}
height={600}
/>
);
}
Loading Data from GraphQL
import { useQuery, gql } from '@apollo/client';
import { GridStorm } from '@gridstorm/react';
const GET_PRODUCTS = gql`
query GetProducts {
products {
id
name
price
category
}
}
`;
function ProductsGrid() {
const { data, loading, error } = useQuery(GET_PRODUCTS);
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
return (
<GridStorm
columns={[
{ field: 'name', headerName: 'Name' },
{ field: 'price', headerName: 'Price', type: 'number' },
{ field: 'category', headerName: 'Category' },
]}
rowData={data.products}
getRowId={(row) => row.id}
height={600}
/>
);
}
Handling Large Datasets
Virtual Scrolling (Client-Side)
GridStorm virtualizes rows by default. Only visible rows plus an overscan buffer are rendered to the DOM. This handles datasets up to ~100K rows efficiently on the client.
<GridStorm
columns={columns}
rowData={largeDataset} // 50,000+ rows
rowHeight={40} // Fixed height enables fast calculation
height={800}
/>
Server-Side Row Model (SSRM)
For datasets beyond 100K rows, use the server-side row model. The grid fetches data in blocks as the user scrolls.
<GridStorm
columns={columns}
rowModelType="serverSide"
dataSource={{
getRows: async (params) => {
const response = await fetch(
`/api/data?start=${params.startRow}&end=${params.endRow}`
+ `&sort=${JSON.stringify(params.sortModel)}`
+ `&filter=${JSON.stringify(params.filterModel)}`
);
const { rows, totalCount } = await response.json();
return { rows, totalCount };
},
}}
height={800}
/>
SSR Considerations
GridStorm's core engine runs in any JavaScript environment, but the DOM renderer and React adapter require a browser. Follow these rules for SSR compatibility:
- Use dynamic imports for the
<GridStorm>component in Next.js (shown above). - Do not import
@gridstorm/dom-rendereron the server. It referencesdocumentandwindow. - The core engine is SSR-safe. You can create a grid engine on the server for data processing (sorting, filtering, aggregation) without a DOM renderer.
- Theme CSS can be imported globally in your layout -- CSS imports are handled by your bundler.
import { createGrid } from '@gridstorm/core';
// This runs on the server -- no DOM needed
const engine = createGrid({ columns, rowData });
engine.api.setSortModel([{ colId: 'revenue', sort: 'desc' }]);
const state = engine.store.getState();
const topRows = state.displayedRowIds.slice(0, 10).map(id => {
const node = state.rowNodes.get(id);
return node?.data;
});
engine.destroy();
Error Handling
The React adapter includes a built-in error boundary. For vanilla usage, listen for errors on the event bus:
engine.eventBus.on('error', (event) => {
console.error(`Grid error from ${event.source}:`, event.error);
});
import { GridStorm } from '@gridstorm/react';
// The built-in GridErrorBoundary catches render errors automatically.
// For custom error UI, wrap with your own error boundary:
<ErrorBoundary fallback={<div>Grid failed to load</div>}>
<GridStorm columns={columns} rowData={rowData} height={600} />
</ErrorBoundary>
TypeScript Configuration
GridStorm requires TypeScript 5.0+ with strict mode. Recommended tsconfig.json settings:
{
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"moduleResolution": "bundler",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"jsx": "react-jsx"
}
}
Typing Row Data
Use generics to get full type safety across columns, row data, and event handlers:
interface Order {
orderId: string;
customer: string;
total: number;
status: 'pending' | 'shipped' | 'delivered';
}
const columns: ColumnDef<Order>[] = [
{ field: 'orderId', headerName: 'Order ID' },
{ field: 'customer', headerName: 'Customer' },
{ field: 'total', headerName: 'Total', type: 'number' },
{ field: 'status', headerName: 'Status' },
];
<GridStorm<Order>
columns={columns}
rowData={orders}
onCellClicked={(e) => {
// e.data is typed as Order
console.log(e.data.customer);
}}
/>
Next Steps
- Performance Guide -- Optimize for large datasets and complex rendering
- Custom Plugins -- Extend GridStorm with your own plugins
- Accessibility -- ARIA roles, keyboard navigation, and screen reader support