| Quick Start Guide | |
|---|---|
| Tutorial Concept |
Build an interactive React PivotTable and field panel to allow users to explore data in the browser in a familiar UI/UX. |
| What You Will Need |
|
| Controls Referenced | SpreadJS - React Spreadsheet Component SpreadJS Optional Pivot Table Add-On Documentation | Online React PivotTable Demos |
Pivot tables are a familiar analysis tool for spreadsheet users, making them a natural fit for reporting and data-heavy React applications. By bringing that recognizable UI and workflow into the browser, developers can reduce the learning curve and make new applications easier to adopt.
In this tutorial, you will learn how to add a React Pivot Table to a web application using SpreadJS and it’s optional JavaScript Pivot Table add-on control. The PivotTable API functionality helps developers deliver an Excel-like data analysis experience without building the interface and reporting logic from scratch. We will build a React 19 application that analyzes video game sales by genre and platform. The finished sample includes:
- A formatted worksheet table containing the source data
- A PivotTable with filter, row, column, and value fields
- Two summarized sales measures
- A searchable, drag-and-drop PivotPanel
- A View Manager for saving useful report layouts

Download a Finished Sample App to Follow Along.
Developer's Guide to Creating a React Pivot Table Component
- Create a React 19 Application
- Install the React Spreadsheet & Pivot Table Packages
- Add a Source Data Table to a React Spreadsheet
- Create & Configure a React PivotTable
- Add a Pivot Panel UI to a React App
- Render the React Pivot Table & Panel
Download a Free Trial of the React Spreadsheet Component Today!
Create a React 19 Application
Start with a Vite React project:
npm create vite@latest spreadjs-react-pivot-panel -- --template react
cd spreadjs-react-pivot-panel
npm install
Vite provides a modern development and production build workflow, while React 19 uses the createRoot client API to render the application.
Update src/main.jsx:
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import App from './app';
createRoot(document.getElementById('root')).render(
<StrictMode>
<App />
</StrictMode>,
);
Install the React Spreadsheet & PivotTable Packages
This application uses the following SpreadJS npm packages:
npm install @mescius/spread-sheets
npm install @mescius/spread-sheets-react
npm install @mescius/spread-sheets-shapes
npm install @mescius/spread-sheets-pivot-addon
At the beginning of src/app.jsx, import React's hooks, the spreadsheet React components, the required plug-ins, and the SpreadJS stylesheet:
import { useCallback, useEffect, useRef, useState } from 'react';
import * as GC from '@mescius/spread-sheets';
import '@mescius/spread-sheets-shapes';
import '@mescius/spread-sheets-pivot-addon';
import { SpreadSheets, Worksheet } from '@mescius/spread-sheets-react';
import '@mescius/spread-sheets/styles/gc.spread.sheets.excel2013white.css';
import { videoGameSalesData } from './pivot-data';
import './styles.css';
```
Note: The import order matters when a project combines SpreadJS plug-ins. Loading Shapes before the PivotTable add-on follows the documented order used when shape-based PivotTable features are part of the application.
Then define a host size and names for the source table and PivotTable:
const hostStyle = {
width: '100%',
height: '100%',
};
const sourceTableName = 'videoGameSales';
const pivotTableName = 'videoGameSalesPivot';
Add a Source Data Table to a React Spreadsheet
The sample data is an array whose first row contains the field names:
export const videoGameSalesData = [
[
'Game Name',
'Platform',
'Year',
'Genre',
'Publisher',
'NA_Sales',
'EU_Sales',
'JP_Sales',
'Other_Sales',
'Global_Sales',
],
// Additional sales records...
];
SpreadJS PivotTables can use a table name or an absolute range formula as their data source. In this sample, we first write the array to the second worksheet and turn that range into a named table:
function configureDataSource(sheet) {
sheet.name('Sales Data');
sheet.setRowCount(videoGameSalesData.length);
sheet.setColumnWidth(0, 220);
sheet.setArray(0, 0, videoGameSalesData);
const sourceTable = sheet.tables.add(
sourceTableName,
0,
0,
videoGameSalesData.length,
videoGameSalesData[0].length,
);
sourceTable.style(GC.Spread.Sheets.Tables.TableThemes.medium2);
}
The table dimensions are calculated from the data instead of being hard-coded. If the sample data changes, the table will continue to cover the full array. Naming the worksheet Sales Data also gives users a convenient way to inspect the records behind the report.
Create & Configure a React PivotTable
Create the PivotTable on the first worksheet and use the source table name as its data source:
function configurePivotTable(sheet) {
sheet.name('Sales Analysis');
const pivotTable = sheet.pivotTables.add(
pivotTableName,
sourceTableName,
1,
1,
GC.Spread.Pivot.PivotTableLayoutType.outline,
GC.Spread.Pivot.PivotTableThemes.medium14,
);
pivotTable.suspendLayout();
pivotTable.options.showRowHeader = true;
pivotTable.options.showColumnHeader = true;
pivotTable.options.bandRows = true;
pivotTable.options.bandColumns = true;
The outline layout keeps the hierarchy readable, while the PivotTable theme provides visual separation between labels, values, and totals. Suspending the layout prevents the PivotTable from recalculating after every field is added.
Next, add a field to each report area:
pivotTable.add(
'Publisher',
'Publisher',
GC.Spread.Pivot.PivotTableFieldType.filterField,
);
pivotTable.add(
'Genre',
'Genre',
GC.Spread.Pivot.PivotTableFieldType.rowField,
);
pivotTable.add(
'Platform',
'Platform',
GC.Spread.Pivot.PivotTableFieldType.columnField,
);
These fields give the initial report a useful structure:
- Publisher filters the records included in the report.
- Genre defines the report rows.
- Platform divides the results into columns.
Finally, add two value fields and summarize both with subtotalType.sum:
pivotTable.add(
'Global_Sales',
'Global Sales',
GC.Spread.Pivot.PivotTableFieldType.valueField,
GC.Pivot.SubtotalType.sum,
);
pivotTable.add(
'NA_Sales',
'North America Sales',
GC.Spread.Pivot.PivotTableFieldType.valueField,
GC.Pivot.SubtotalType.sum,
);
pivotTable.resumeLayout();
pivotTable.autoFitColumn();
return pivotTable;
}
The second argument passed to add is the display name. User-friendly captions such as Global Sales are easier to understand than the source field name Global_Sales.
After every field is configured, resumeLayout generates the report and autoFitColumn sizes its columns.
Add a Pivot Panel UI to a React App
The Pivot Panel is the interactive UI report builder displayed beside the spreadsheet. It contains three sections:
| PivotTable Fields: Lists and searches the fields available in the data source. | ![]() |
| PivotTable Area: Lets users drag fields between Filters, Rows, Columns, and Values. | |
|
Pivot View Manager: Saves and restores different PivotTable field layouts. |
The PivotPanel requires a PivotTable instance and an HTML host element. Store those values with React state and refs:
export default function App() {
const panelHostRef = useRef(null);
const pivotPanelRef = useRef(null);
const [pivotTable, setPivotTable] = useState(null);
Initialize the workbook through the React component's `workbookInitialized` callback:
const initializeWorkbook = useCallback((workbook) => {
workbook.suspendPaint();
const pivotSheet = workbook.getSheet(0);
const dataSheet = workbook.getSheet(1);
configureDataSource(dataSheet);
setPivotTable(configurePivotTable(pivotSheet));
workbook.resumePaint();
}, []);
The PivotPanel host ref is available after React commits the component to the DOM. Create the PivotPanel in an effect so both the host and PivotTable exist:
useEffect(() => {
if (!pivotTable || !panelHostRef.current) {
return undefined;
}
const pivotPanel = new GC.Spread.Pivot.PivotPanel(
'videoGameSalesPanel',
pivotTable,
panelHostRef.current,
);
pivotPanel.sectionVisibility(
GC.Spread.Pivot.PivotPanelSection.fields |
GC.Spread.Pivot.PivotPanelSection.area |
GC.Spread.Pivot.PivotPanelSection.viewList,
);
pivotPanelRef.current = pivotPanel;
return () => {
pivotPanel.destroy();
if (pivotPanelRef.current === pivotPanel) {
pivotPanelRef.current = null;
}
};
}, [pivotTable]);
The sectionVisibility setting explicitly enables the field list, report areas, and View Manager. Calling destroy() in the effect cleanup releases the PivotPanel when React replaces the PivotTable or unmounts the component.
Render the React Spreadsheet & PivotPanel
Return two worksheets inside the SpreadSheets component and place the panel host beside it:
return (
<main className="demo-shell">
<header className="demo-header">
<div>
<p className="eyebrow">SpreadJS PivotTable add-on</p>
<h1>Video game sales explorer</h1>
</div>
<p className="demo-intro">
Drag fields between Filters, Rows, Columns, and Values to reshape the
analysis. Save useful layouts in the View Manager.
</p>
</header>
<section className="demo-workspace" aria-label="Interactive sales analysis">
<div className="spread-host">
<SpreadSheets
hostStyle={hostStyle}
workbookInitialized={initializeWorkbook}
>
<Worksheet />
<Worksheet />
</SpreadSheets>
</div>
<aside className="pivot-sidebar" aria-label="PivotTable field controls">
<div className="panel-heading">
<p className="eyebrow">Build your report</p>
<h2>PivotTable Fields</h2>
<p>
Search, select, or drag a field to update the report instantly.
</p>
</div>
<div ref={panelHostRef} className="pivot-panel-host" />
</aside>
</section>
</main>
);
}
Give both hosts an explicit height. The React spreadsheet and PivotPanel need available layout space to render correctly:
.demo-workspace {
display: grid;
grid-template-columns: minmax(0, 1fr) 360px;
min-height: 620px;
gap: 16px;
}
.spread-host {
height: 100%;
min-width: 0;
overflow: hidden;
}
.pivot-sidebar {
display: grid;
grid-template-rows: auto minmax(0, 1fr);
min-width: 0;
overflow: hidden;
}
.pivot-panel-host {
width: 100%;
height: 100%;
min-height: 0;
overflow: auto;
}
Run the application:
npm run dev
The initial report displays global and North American sales by genre and platform:

Integrating PivotTables into a React application gives users a familiar, flexible way to summarize data while keeping the full reporting experience inside the application.
Users can now:
- Select or clear fields with checkboxes.
- Search the source field list.
- Drag fields between the four report areas.
- Open the Publisher filter in the worksheet.
- Change the calculation used by a value field.
- Save and restore layouts with the View Manager.
- Open the Sales Data sheet to inspect the source table.
Learn More About Working with React PivotTable Components
This sample demonstrates the main pieces required for a React PivotTable experience, but the add-on also supports features such as custom layouts, formatting, grouping, filtering, sorting, calculated fields, multiple value calculations, and slicers.
To learn more, check out the following resources:
- SpreadJS with React documentation
- SpreadJS PivotTable overview
- SpreadJS PivotPanel demo
- SpreadJS licensing documentation
Happy Coding!
