|
| 1 | +--- |
| 2 | +title: Charts - Performance |
| 3 | +productId: x-charts |
| 4 | +--- |
| 5 | + |
| 6 | +# Charts - Performance |
| 7 | + |
| 8 | +<p class="description">Learn how to keep charts fast and responsive when rendering large datasets.</p> |
| 9 | + |
| 10 | +The performance of a chart can be decomposed in multiple factors: The time for computations, the React re-renders time, the time for the DOM update. |
| 11 | +This page describes the most impactful options you can use to keep rendering smooth. |
| 12 | + |
| 13 | +## Provide stable references |
| 14 | + |
| 15 | +Charts derive a lot of state from their axes/series and recompute it whenever the relevant prop changes by reference. |
| 16 | +Passing a new array or object on every render forces this work to run again and triggers extra re-renders, even when the data itself hasn't changed. |
| 17 | + |
| 18 | +The following props benefit from a stable reference: |
| 19 | + |
| 20 | +- `series` |
| 21 | +- `xAxis`, `yAxis`, and `zAxis` |
| 22 | +- `dataset` |
| 23 | +- `margin` |
| 24 | +- `colors` |
| 25 | + |
| 26 | +When the value never changes, define it outside the component so the same reference is reused across renders: |
| 27 | + |
| 28 | +```jsx |
| 29 | +// Defined once, outside the component. |
| 30 | +const xAxis = [{ scaleType: 'band', data: ['A', 'B', 'C'] }]; |
| 31 | + |
| 32 | +function MyChart() { |
| 33 | + return <BarChart xAxis={xAxis} series={series} height={300} />; |
| 34 | +} |
| 35 | +``` |
| 36 | + |
| 37 | +When the value depends on props or state, wrap it in `useMemo` so it is only recomputed when its inputs change: |
| 38 | + |
| 39 | +```jsx |
| 40 | +function MyChart({ data }) { |
| 41 | + const series = React.useMemo(() => [{ data }], [data]); |
| 42 | + |
| 43 | + return <LineChart series={series} height={300} />; |
| 44 | +} |
| 45 | +``` |
| 46 | + |
| 47 | +:::warning |
| 48 | +The docs uses lot of inlined objects and arrays directly in the JSX (for example `margin={{ top: 10 }}` or `series={[{ data }]}`). |
| 49 | + |
| 50 | +We do that for clarity in the docs sections. |
| 51 | +But each render creates a new reference, which defeats the internal memoization. |
| 52 | +::: |
| 53 | + |
| 54 | +## Skip animations |
| 55 | + |
| 56 | +Animations are convenient for small charts, but they require updating the DOM on every frame. |
| 57 | +With many data points, this work multiplies. |
| 58 | + |
| 59 | +Set the `skipAnimation` prop to render the final state directly, without transitions: |
| 60 | + |
| 61 | +```jsx |
| 62 | +<LineChart series={series} skipAnimation /> |
| 63 | +``` |
| 64 | + |
| 65 | +:::info |
| 66 | +When `skipAnimation` is unset, charts already respect the user's [`prefers-reduced-motion`](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-reduced-motion) setting and skip animations for users who opted out of motion. |
| 67 | +::: |
| 68 | + |
| 69 | +## Remove marks from line charts |
| 70 | + |
| 71 | +If you set `showMark` to `true` for line series, a mark element is render for every data point. |
| 72 | +For a series with thousands of points, this adds thousands of DOM nodes that can impact performances. |
| 73 | + |
| 74 | +Either disable marks, or reduce their number |
| 75 | + |
| 76 | +```jsx |
| 77 | +// One mark per 100 values. |
| 78 | +showMark: ({ index }) => index % 100 === 0; |
| 79 | +// Only a mark at the end of the series. |
| 80 | +showMark: 'end'; |
| 81 | +// Only a mark at the beginning of the series. |
| 82 | +showMark: 'start'; |
| 83 | +``` |
| 84 | + |
| 85 | +See [Line charts—Optimization](/x/react-charts/lines/#optimization) for more details. |
| 86 | + |
| 87 | +## Use a more efficient renderer |
| 88 | + |
| 89 | +By default, each item is drawn as its own SVG element—a `<rect>` per bar, a `<circle>` per scatter point. |
| 90 | +This is flexible but doesn't scale well: the number of DOM nodes grows with the number of data points. |
| 91 | + |
| 92 | +Bar and scatter charts accept a `renderer` prop to switch to a more efficient drawing strategy: |
| 93 | + |
| 94 | +- `'svg-single'` (default): renders every item in its own SVG element. |
| 95 | +- `'svg-batch'`: batches all items into a few `<path>` elements, which dramatically reduces the DOM node count for large datasets. |
| 96 | + |
| 97 | +```jsx |
| 98 | +<BarChart series={series} renderer="svg-batch" /> |
| 99 | +``` |
| 100 | + |
| 101 | +The batch renderer comes with some trade-offs, such as not being able to style individual items with CSS. |
| 102 | +See the dedicated sections for the full list of limitations and live demos: |
| 103 | + |
| 104 | +- [Bar charts—Performance](/x/react-charts/bars/#svg-batch-rendering) |
| 105 | +- [Scatter charts—Performance](/x/react-charts/scatter/#svg-batch-rendering) |
| 106 | + |
| 107 | +### WebGL renderer [<span class="plan-premium"></span>](/x/introduction/licensing/#premium-plan 'Premium plan') |
| 108 | + |
| 109 | +For the largest datasets, `BarChartPremium`, `ScatterChartPremium`, and `HeatmapPremium` support a `'webgl'` renderer that draws items into a single `<canvas>` element, using GPU. |
| 110 | +This trades item-level interactivity for the ability to render hundreds of thousands of points. |
| 111 | + |
| 112 | +```jsx |
| 113 | +<ScatterChartPremium series={series} renderer="webgl" /> |
| 114 | +``` |
| 115 | + |
| 116 | +See [Bar charts—WebGL renderer](/x/react-charts/bars/#webgl-renderer), [Scatter charts—WebGL renderer](/x/react-charts/scatter/#webgl-renderer), and [Heatmap—WebGL renderer](/x/react-charts/heatmap/#webgl-renderer) for details and demos. |
0 commit comments