Skip to main content

Imperative Handles

Imperative handles are a key performance feature of XFrames. They let you push data directly from JavaScript into the C++ rendering core, bypassing React's reconciliation entirely — no virtual DOM diffing, no re-renders. The data goes straight to ImGui.

This matters because ImGui only renders what is visible in the viewport. A Table with a large dataset renders at the same speed as one with ten rows — only the visible rows are drawn each frame. The same applies to plots: data is stored in C++ vectors and rendered natively by ImPlot. You can incrementally stream data via appendData calls over time and the UI stays responsive throughout.

Usage pattern

import { useRef, useCallback } from "react";
import { TableImperativeHandle } from "@xframes/common";

function MyComponent() {
const tableRef = useRef<TableImperativeHandle>(null);

const loadData = useCallback(() => {
// This data goes directly to C++ — no React re-renders
tableRef.current?.setTableData(data);
}, []);

return <XFrames.Table ref={tableRef} columns={columns} initialData={[]} />;
}

All handle types are imported from @xframes/common.


Table

TableImperativeHandle

MethodParametersDescription
setTableDatadata: any[]Replace all table rows
appendDataToTabledata: any[]Append rows to existing data
setColumnFiltercolumnIndex: number, filterText: stringSet filter for a specific column
clearFiltersClear all active column filters
const ref = useRef<TableImperativeHandle>(null);

// Replace data
ref.current?.setTableData([{ city: "Tokyo", pop: "37400068" }]);

// Append rows
ref.current?.appendDataToTable([{ city: "Delhi", pop: "30290936" }]);

// Filter column 0
ref.current?.setColumnFilter(0, "Tokyo");

// Clear all filters
ref.current?.clearFilters();

Plots

PlotLineImperativeHandle

MethodParametersDescription
appendDatax: number, y: numberAppend point to the first series
appendSeriesDataseriesIndex: number, x: number, y: numberAppend point to a specific series
setDataseriesData: { data: { x: number; y: number }[] }[]Replace all series data
setAxesDecimalDigitsx: number, y: numberSet decimal precision for axis labels
setAxesAutoFitenabled: booleanEnable/disable auto-fit axes to data range
resetDataClear all data
const ref = useRef<PlotLineImperativeHandle>(null);

// Single-series streaming
ref.current?.appendData(Date.now(), sensorValue);

// Multi-series batch update
ref.current?.setData([
{ data: [{ x: 0, y: 1 }, { x: 1, y: 3 }] }, // series 0
{ data: [{ x: 0, y: 2 }, { x: 1, y: 1 }] }, // series 1
]);

PlotBarImperativeHandle

MethodParametersDescription
setDatadata: { x: number; y: number }[]Replace all bars (x = position, y = height)
appendDatax: number, y: numberAppend a single bar
setAxesAutoFitenabled: booleanEnable/disable auto-fit axes
resetDataClear all data
const ref = useRef<PlotBarImperativeHandle>(null);

ref.current?.setData([
{ x: 0, y: 10 },
{ x: 1, y: 25 },
{ x: 2, y: 15 },
]);

PlotScatterImperativeHandle

MethodParametersDescription
setDatadata: { x: number; y: number }[]Replace all scatter points
appendDatax: number, y: numberAppend a single point
setAxesAutoFitenabled: booleanEnable/disable auto-fit axes
resetDataClear all data
const ref = useRef<PlotScatterImperativeHandle>(null);

ref.current?.setData([
{ x: 1.5, y: 2.3 },
{ x: 3.1, y: 4.7 },
]);

PlotHeatmapImperativeHandle

MethodParametersDescription
setDatarows: number, cols: number, values: number[]Set grid data (flat row-major array)
setAxesAutoFitenabled: booleanEnable/disable auto-fit axes
resetDataClear all data

The values array is a flat 1D array in row-major order with rows × cols elements. Bounds are set to (0,0)–(cols,rows) so cells map 1:1 to plot coordinates.

const ref = useRef<PlotHeatmapImperativeHandle>(null);

// 3×3 grid
ref.current?.setData(3, 3, [
10, 20, 30,
40, 50, 60,
70, 80, 90,
]);

PlotHistogramImperativeHandle

MethodParametersDescription
setDatavalues: number[]Replace raw values (auto-binned per bins prop)
appendDatavalue: numberAppend a single value
setAxesAutoFitenabled: booleanEnable/disable auto-fit axes
resetDataClear all data

Unlike PlotBar which takes explicit X/Y pairs, histogram takes raw values and bins them automatically.

const ref = useRef<PlotHistogramImperativeHandle>(null);

ref.current?.setData([1.2, 2.3, 2.8, 3.1, 3.5, 4.0, 4.2]);
ref.current?.appendData(5.1);

PlotPieChartImperativeHandle

MethodParametersDescription
setDatadata: { label: string; value: number }[]Set pie slices (label + value pairs)
resetDataClear all data

Batch-only — no appendData. The chart renders with equal aspect ratio.

const ref = useRef<PlotPieChartImperativeHandle>(null);

ref.current?.setData([
{ label: "Desktop", value: 65 },
{ label: "Mobile", value: 30 },
{ label: "Tablet", value: 5 },
]);

PlotCandlestickImperativeHandle

MethodParametersDescription
setDatadata: PlotCandlestickDataItem[]Set OHLC candlestick data
setAxesAutoFitenabled: booleanEnable/disable auto-fit axes
resetDataClear all data

Each data item has the shape:

type PlotCandlestickDataItem = {
date: number; // Unix timestamp
open: number;
close: number;
low: number;
high: number;
};
const ref = useRef<PlotCandlestickImperativeHandle>(null);

ref.current?.setData([
{ date: 1704067200, open: 100, close: 105, low: 98, high: 108 },
{ date: 1704153600, open: 105, close: 102, low: 99, high: 107 },
]);

Form controls

ComboImperativeHandle

MethodParametersDescription
setSelectedIndexindex: numberSet the selected option by zero-based index
const ref = useRef<ComboImperativeHandle>(null);

<XFrames.Combo ref={ref} options={["Option A", "Option B"]} initialSelectedIndex={0} />

// Programmatically select "Option B"
ref.current?.setSelectedIndex(1);

InputTextImperativeHandle

MethodParametersDescription
setValuevalue: stringSet the input text value
const ref = useRef<InputTextImperativeHandle>(null);

<XFrames.InputText ref={ref} defaultValue="" onChange={handleChange} />

// Programmatically set text
ref.current?.setValue("Hello World");

Other

ImageImperativeHandle

MethodParametersDescription
reloadForce reload the image from its current URL
const ref = useRef<ImageImperativeHandle>(null);

<XFrames.Image ref={ref} url="https://example.com/chart.png" />

ref.current?.reload();

ClippedMultiLineTextRendererImperativeHandle

MethodParametersDescription
appendTextToClippedMultiLineTextRendererdata: stringAppend text to the renderer
const ref = useRef<ClippedMultiLineTextRendererImperativeHandle>(null);

<XFrames.ClippedMultiLineTextRenderer ref={ref} />

ref.current?.appendTextToClippedMultiLineTextRenderer("Log line 1\n");

MapImperativeHandle

MethodParametersDescription
rendercenterX: number, centerY: number, zoom: numberRender map at given center coordinates and zoom level
const ref = useRef<MapImperativeHandle>(null);

<XFrames.MapView ref={ref} />

// Center on New York at zoom 12
ref.current?.render(40.7128, -74.006, 12);

Next steps

  • Event types — all event types and their payloads
  • Plots — plot component props and configuration
  • Table — full table configuration guide