React
Use Reeflow components in your React applications with full TypeScript support and React-specific hooks.
Installation
Section titled “Installation”npm install @reeflow/reactQuick start
Section titled “Quick start”import { ReeflowProvider, ReeflowBarChart } from '@reeflow/react';
function App() { return ( <ReeflowProvider authToken="your-api-key"> <ReeflowBarChart title="Revenue by Product" query={{ type: 'aggregate', query: { measures: [{ column: 'orders.total_amount', type: 'sum', label: 'Revenue' }], dimensions: [{ column: 'orders.product_name', type: 'categorical' }], }, }} /> </ReeflowProvider> );}React hooks
Section titled “React hooks”The React SDK provides the useReeflowComponent hook for accessing component state, data, and control methods:
import { useReeflowComponent } from '@reeflow/react';
function MyChart() { const { isLoading, isError, error, data } = useReeflowComponent('my-chart');
return ( <div> {isLoading && <p>Loading...</p>} {isError && <p>Error: {error?.message}</p>} {data && <p>Loaded {data.row_count} rows</p>}
<ReeflowBarChart id="my-chart" query={query} /> </div> );}See React Hooks for complete documentation.
Event handling
Section titled “Event handling”All React components include auto-generated event handler props for standard events (onStateChange, onDataLoaded, onError) and component-specific events:
<ReeflowBarChart id="chart" query={query} onDataLoaded={(event) => console.log('Data loaded:', event.detail)} onChartClick={(event) => console.log('Chart clicked:', event.detail)}/>;Best practices
Section titled “Best practices”1. Inline queries are supported
Section titled “1. Inline queries are supported”You can pass query objects directly inline without needing useMemo(). The SDK automatically performs deep equality checks to prevent unnecessary re-executions:
// ✅ This works perfectly - no useMemo needed!<ReeflowBarChart query={{ type: 'aggregate', query: { measures: [{ column: 'revenue', type: 'sum' }], }, }}/>;You can still use useMemo() if the query depends on props or state variables:
const query = useMemo( () => ({ type: 'aggregate', query: { measures: [{ column: selectedField, type: 'sum' }], }, }), [selectedField], // Re-create only when selectedField changes);2. Use as const for better typing
Section titled “2. Use as const for better typing”TypeScript will infer better types when you use as const:
const query = { type: 'aggregate' as const, // ✅ Infers 'aggregate', not string query: { measures: [ { column: 'revenue', type: 'sum' as const }, // ✅ Infers 'sum', not string ], },};3. Use hooks instead of refs
Section titled “3. Use hooks instead of refs”For accessing component state, prefer hooks over refs:
function MyChart() { const { data, isLoading } = useReeflowComponent('chart');
return ( <div> {isLoading && <Spinner />} <ReeflowBarChart id="chart" query={query} /> </div> );}function MyChart() { const chartRef = useRef<ReeflowBarChartElement>(null);
const handleRefresh = () => { chartRef.current?.refresh(); };
return ( <div> <button onClick={handleRefresh}>Refresh</button> <ReeflowBarChart ref={chartRef} query={query} /> </div> );}4. Handle loading and error states
Section titled “4. Handle loading and error states”Always provide user feedback:
function MyChart() { const { isLoading, isError, error } = useReeflowComponent('my-chart');
return ( <div> {isLoading && <LoadingSpinner />} {isError && <ErrorMessage error={error} />}
<ReeflowBarChart id="my-chart" query={query} /> </div> );}TypeScript support
Section titled “TypeScript support”The React SDK is fully typed. Import types from @reeflow/core:
import type { QueryResult, ReeflowError, JSONQLQuery } from '@reeflow/core';import type { ReeflowBarChartProps } from '@reeflow/react';
const query: JSONQLQuery = { type: 'aggregate', query: { measures: [{ column: 'revenue', type: 'sum' }], },};Examples
Section titled “Examples”Dashboard with multiple charts
Section titled “Dashboard with multiple charts”import { ReeflowBarChart, ReeflowLineChart, useReeflowComponent } from '@reeflow/react';
function Dashboard() { const revenue = useReeflowComponent('revenue-chart'); const orders = useReeflowComponent('orders-chart');
const isLoading = revenue.isLoading || orders.isLoading;
return ( <div> {isLoading && <p>Loading dashboard...</p>}
<ReeflowLineChart id="revenue-chart" title="Revenue" query={{ type: 'aggregate', query: { measures: [{ column: 'orders.total_amount', type: 'sum' }], dimensions: [{ column: 'orders.order_date', type: 'time', granularity: 'month' }], }, }} /> <ReeflowBarChart id="orders-chart" title="Orders" query={{ type: 'aggregate', query: { measures: [{ column: 'orders.order_id', type: 'count' }], dimensions: [{ column: 'orders.order_date', type: 'time', granularity: 'month' }], }, }} /> </div> );}Interactive table with row selection
Section titled “Interactive table with row selection”import { ReeflowTable } from '@reeflow/react';import { useState } from 'react';
function OrdersTable() { const [selected, setSelected] = useState(null);
return ( <div> <ReeflowTable id="orders" title="Orders" query={{ type: 'table', query: { columns: [ { name: 'orders.order_id' }, { name: 'orders.customer_name' }, { name: 'orders.total_amount' }, ], }, }} onTableRowClick={(event) => setSelected(event.detail.row)} />
{selected && ( <div> <h3>Selected Order</h3> <pre>{JSON.stringify(selected, null, 2)}</pre> </div> )} </div> );}Next steps
Section titled “Next steps”- React Hooks - Complete hooks documentation
- Charts - Chart component details
- Table - Table component details
- React API Reference - Full TypeScript API