Getting started with React¶
pivotkit-react is the report builder as the React component <PivotReport>, for React 18 and 19.
You put a report into a React app in a few steps: install the package, render <PivotReport> with
your rows, then add what your app needs - keep the view, save views, react to clicks. Each step adds
one or two props to the one before it.
1. Install¶
npm install pivotkit-react react react-dom echarts
React, ReactDOM and Apache ECharts are peer dependencies: your app provides them, so the page has
one copy of each. pivotkit-core (a caret range) and @dnd-kit/core and @dnd-kit/sortable (pinned
exactly) come with the package.
| Peer | Range | Why it is a peer |
|---|---|---|
react, react-dom |
>=18.2 <20 |
Hooks break with two copies of React in one page. Every browser test runs on React 18 and on React 19. |
echarts |
>=6.1.0 <7 |
About 1 MB; an app that draws its own charts has it already. It is loaded on the first chart, so a report that never shows one does not load it. |
Using pivotkit-core directly as well
pivotkit-react depends on a caret range of pivotkit-core (^0.2.0). In 0.x a caret range spans
patch versions only (^0.2.0 is 0.2.x), so an app that imports pivotkit-core itself must use a
version inside that range; npm shares one copy only when the ranges overlap.
2. Render the first report¶
import { PivotReport } from "pivotkit-react";
import "pivotkit-react/styles.css";
const rows = [
{ Region: "North", Product: "A", Sales: 120, Date: "2026-01-05" },
{ Region: "South", Product: "B", Sales: 340, Date: "2026-02-14" }
// ...
];
export function SalesReport() {
return (
<PivotReport
data={rows}
defaultView={{ rows: ["Region"], cols: ["Product"], values: [{ field: "Sales", agg: "sum" }] }}
height={640}
/>
);
}
datais an array of plain objects. Every key is a field; numbers, text, booleans and dates (Dateobjects or ISO strings such as"2026-01-05") are recognised by themselves.defaultViewis the start: a view, plain JSON. Leave it out and the report starts empty with a short guide.- Import
pivotkit-react/styles.cssonce. Every colour and size is a--pk-*token you can override. heightis the report's height (default 640 px); the table and the field list scroll inside it.
3. Keep the view in your app¶
To store the report, or start it from a saved one, make it controlled: pass view and set it
from onViewChange. The undo history stays inside the report however often your app renders.
import { useState } from "react";
export function TicketReport({ rows }) {
const [view, setView] = useState(presets[0].view);
return <PivotReport data={rows} view={view} onViewChange={setView} />;
}
const presets = [
{ name: "Tickets per team", view: { rows: ["Team"], cols: ["Priority"], values: [{ field: "Ticket", agg: "count" }] } }
];
Store view wherever your app keeps settings; it is plain JSON.
4. Tell the report when the data is new¶
<PivotReport data={rows} dataKey="tickets" view={view} onViewChange={setView} />
dataKey tells the report when the data is new. An app that builds a new array on every render
passes a key, and the rows are encoded again only when it changes.
5. Offer saved views¶
<PivotReport
data={rows}
dataKey="tickets"
view={view}
onViewChange={setView}
templates={[...presets, ...saved.map((t) => ({ ...t, scope: "user", deletable: true }))]}
onSaveTemplate={(name, v) => saveTemplate({ name, view: v })}
onDeleteTemplate={(name, { scope }) => deleteTemplate(name, scope)}
/>
templates fill the Views menu, in two groups: Shared views (the presets) and My views (the
deletable ones); onSaveTemplate adds "Save current view" and Save for a loaded view of the user's (it may get a name that exists: replace that view). Both callbacks may return a promise: the
report shows "Saved" when it resolves and an error when it rejects. Without a server,
templateStore="browser" keeps the user's views in the browser; shared views, publishing and views
from an OpenAPI document are in Templates and shared views.
6. Set what a field gets¶
<PivotReport
data={rows}
fieldDefaults={{ "Lead hours": { agg: "average", format: "duration:h" } }}
/>
fieldDefaults set the aggregator and format a field gets when someone adds it to Values, and the
custom order of its items (order) on Rows or Columns. Labels, descriptions and links of fields are
in Field descriptions and names.
7. React to clicks¶
<PivotReport data={rows} onCellClick={({ row, col, count }) => console.log(row, col, count)} />
onCellClick gets every click on a value or a chart point, with the rows behind it.
8. Language and the data's name¶
<PivotReport data={rows} locale="de-DE" source={{ id: "tickets", name: "Tickets" }} />
localesets numbers, dates and sorting, and the language of the labels (de-*is German).source({ id, name }) names the data: shared views carry it, and a view made for other data asks before it is loaded (Sharing).
All props are listed in the pivotkit-react reference.
Bundlers and import maps¶
dist/index.js is an ES module whose imports stay bare: react, react-dom, pivotkit-core,
pivotkit-core/export, pivotkit-core/link, pivotkit-core/templates (with the menus),
@dnd-kit/core and @dnd-kit/sortable. On the first chart it loads
./echarts.js next to it, which imports echarts/core, echarts/charts, echarts/components and
echarts/renderers by name, so a bundler keeps only the four chart types the report draws. Any
bundler that understands ES modules resolves them. A page without a bundler maps each bare name to a
file with an import map;
the browser tests load the package that way.
The build compiles JSX to React.createElement, so the app needs react and react-dom only, no
JSX runtime.
PowerShell Universal¶
PowerShell Universal renders custom components with React 18.3.1, which it provides at runtime.
pivotkit-react fits that model: React and ECharts stay outside the package, the report follows the
data-theme="light|dark" attribute that PowerShell Universal sets on <html>, and it keeps its undo
history when the host renders it again on every change. The browser tests run it on a host page that
takes React from an import map and renders again all the time, the way PowerShell Universal does.
A ready-made module is
PowerShellUniversal.Component.Pivot
(New-UDPivotReport, a separate project): the report with saved and shared views, roles, and the app's
theme. A component of your own bundles pivotkit-react with pivotkit-core, @dnd-kit and ECharts, and
leaves React and ReactDOM to PowerShell Universal.
Next steps¶
- Recipes: tasks such as links, the browser store, chart options, a strict Content-Security-Policy.
- Views and saved views: the JSON behind every report.
- Theming and Localisation.
- Use a report: what the people using it can do; point them there.