TanStack
Getting Started

React Adapter

@tanstack/react-charts is a thin lifecycle and SSR adapter around @tanstack/charts. Chart definitions, scale resolution, guide layout, scenes, rendering, animation, and interaction remain in the framework-neutral core.

Public exports

ts
export { Chart } from '@tanstack/react-charts'

export type {
  ChartCommonProps,
  ChartProps,
  ChartDefinition,
  ChartPoint,
  ChartTooltipBodyRenderContext,
} from '@tanstack/react-charts'

Choose Canvas or an application-supplied renderer through an explicit subpath:

tsx
import { Chart as CanvasChart } from '@tanstack/react-charts/canvas'
import { Chart as RendererChart } from '@tanstack/react-charts/core'

CanvasChart selects the optional built-in renderer. RendererChart requires a renderer prop. The default Chart remains SVG-based, so importing the default adapter does not pull Canvas into its module graph.

Use the re-exported definition and point types only when an application API needs an explicit annotation. Ordinary component use is inferred.

Render lifecycle

The adapter creates one ChartRuntime per mounted component and asks the selected renderer for its initial markup during React render. After commit:

  1. a layout effect mounts the shared DOM host into the existing chart surface
  2. the same runtime is passed to the host
  3. a second layout effect forwards the latest complete host options
  4. later React commits call host.update; a new definition identity rebuilds the scene
  5. effect cleanup destroys the host and runtime-owned browser behavior

The chart surface is memoized after its first render. Scene changes are painted by the shared host rather than by rebuilding the surface through React. Memoize definitions that capture component values with useMemo; module-scope definitions need no component memoization.

React batching may omit intermediate application states. Every committed prop set forwarded to the host remains declarative and complete.

SSR and hydration

The default SVG entry emits:

  • the outer .ts-chart-host div
  • a .ts-chart-surface div
  • the complete accessible shared SVG at initialWidth

The client renders the same initial structure, then the layout effect adopts and reconciles that SVG. There is no placeholder-only server mode.

The Canvas entry emits the same outer structure with a named Canvas root and two aria-hidden canvases. It does not paint pixels on the server. The client adopts those elements, paints after mount, and attaches the same focus, keyboard, tooltip, and selection host.

Use deterministic data, scale domains, definitions, dimensions, and custom renderers on server and client. The adapter generates a sanitized idPrefix from React.useId() when one is not supplied, keeping document resources stable through hydration.

tabIndex defaults to 0 on both server and client. keyboard: false forces it to -1.

For resource-aware gradients or clipping, pass the same renderer on both server and client. See Rendering and export.

Sizing and layout

The adapter renders two nested containers:

plaintext
.ts-chart-host
  .ts-chart-surface
    svg.ts-chart | div.ts-chart-canvas

The outer host has position: relative.

PropsOuter host behaviorScene behavior
no width, fixed heightwidth: 100%; fixed heightcontainer width × fixed height
fixed width and heightfixed CSS width and heightsame fixed scene dimensions
fixed width and aspectRatiofixed width and CSS ratiofixed width divided by ratio
positive aspectRatio, no heightwidth: 100%; CSS aspect ratiomeasured width divided by ratio
neither height nor aspectRatiowidth: 100%; height: 320pxmeasured width × 320

initialWidth defaults to 640 and controls the initial/server scene when width is absent. A fixed height takes precedence over aspectRatio. Nonpositive and nonfinite ratios fall back to the default height.

The DOM host observes responsive width and measures the inherited container font. Its exact fallback and relayout behavior is documented in DOM host.

className and style

React-specific presentation props apply to the outer .ts-chart-host:

tsx
<Chart
  definition={definition}
  ariaLabel="Revenue"
  className="dashboard-chart"
  style={{ minHeight: 240, color: 'var(--foreground)' }}
/>
  • className is appended after ts-chart-host.
  • style is React.CSSProperties.
  • custom style fields override the adapter's computed position, width, height, and aspect ratio because they are spread last.

Do not give style.width a value that conflicts with a fixed width prop. The style controls the outer CSS box, while the prop continues to lock the scene width.

Core renderer className options apply to a surface when calling it directly. The React adapter's className intentionally owns the outer element instead.

Tooltip body composition

renderTooltipBody mounts React content into the native tooltip surface. Its context provides points, content, defaultBody, pinned, and dismiss. Composing defaultBody keeps the core title, rows, formatting, and swatches; arbitrary React content can sit beside it.

The shared host owns a stable body mount target and releases it when the tooltip is hidden, custom rendering is disabled, or the chart is destroyed. React owns the rendered component lifecycle. A custom body is inert while transient, so display-only content can remain visible but controls should render only while pinned is true. Definition tooltip.portal: true promotes the whole surface above clipped ancestors without changing this React API.

Definition and input identity

Define a fixed chart outside component render:

tsx
import { defineChart } from '@tanstack/charts'

const definition = defineChart({
  marks: [],
  x: null,
  y: null,
})

For live state, memoize the complete definition against the values it captures. Definition identity is the application update boundary; see Chart Definition API.

Callback freshness

Every committed prop set is forwarded to the host. Focus, grouped focus, selection, and render callbacks therefore use the latest committed functions. Callback types are inferred from the definition's marks.

Core boundary

The adapter does not redefine:

  • marks or chart specs
  • D3 scale and transform ownership
  • tooltip and focus semantics
  • animation and reconciliation
  • custom marks or renderers

Use Scales and D3 for the injected primitive boundary and the core reference for those APIs.