Library / SDK
plotly/react-plotly.js avatar
plotly/react-plotly.js

react-plotly.js: a React component that hands your zoom and pan state back to you

A plotly.js React component from Plotly 📈

1,097 stars138 forksJavaScriptMIT

At a glance

What is it?
react-plotly.js is Plotly's React wrapper around plotly.js, and it is deliberately a dumb component, which means the interesting work is in the props. The component refreshes through `Plotly.react` under three specific conditions, and it refuses to merge its own state with yours, so a zoom performed by the user has to be captured through `onUpdate` or it is lost on the next render.
Who is it for?
Adopt react-plotly.js if you are rendering Plotly charts inside React and you want the full plotly.js API rather than a subset, and if you are prepared to hold the figure state in your own component. Do not adopt it expecting a stateful chart component, because the README is explicit that it does not merge its internal state with your updates, and the cost of that design is that you have to upstream user interactions yourself.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 37 days ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A thin wrapper, and the philosophy behind it

react-plotly.js is described as a plotly.js React component from Plotly, and the README does not oversell it. It is a component that takes plotly.js's own vocabulary, with `data` as a list of trace objects, `layout` as the layout object and `config` as the configuration object, and it points you at the plotly.js JavaScript API documentation and the full attribute listing for everything else. The design principle is stated in the state management section, where the component is called a dumb component that does not merge its internal state with any updates. That is a deliberate choice with a clear cost and a clear benefit. The benefit is that the component stays thin and does not become a second state management layer between your data and plotly.js. The cost is that everything the user does inside the plot, such as zooming or panning, is yours to keep. The installation is two packages, since the component and the library it wraps are separate, and the README shows the minimum component usage with a scatter trace and a bar trace in the same figure.

The state problem, and the pattern the README recommends

Because the component does not merge state, the README explains the consequence plainly: if a user interacts with the plot, by zooming or panning for example, any subsequent re-renders will lose that information unless it is captured and upstreamed through the `onUpdate` callback prop. The recommended pattern is to hold the whole figure in your own state and wire both callbacks to it, so that the component's internal view of the figure is continuously replaced by whatever you know about it.

javascript
import {useState} from 'react';
import Plot from 'react-plotly.js';

function App() {
  const [figure, setFigure] = useState({data: [], layout: {}, frames: [], config: {}});
  return (
    <Plot
      data={figure.data}
      layout={figure.layout}
      frames={figure.frames}
      config={figure.config}
      onInitialized={setFigure}
      onUpdate={setFigure}
    />
  );
}

The two callbacks are doing different jobs. `onInitialized` fires when the plot has been set up, and `onUpdate` fires when the plot is updated because of new data or layout, or when the user interacts with it. Passing the same setter to both is what closes the loop: the figure your component holds is always the figure on screen, including the zoom level the user just dragged to.

When the chart actually redraws

This is the section that decides whether the component works for you, and the rules are narrow. The component refreshes the plot through `Plotly.react` if the `revision` prop is defined and has changed, or if one of `data`, `layout` or `config` has changed identity as checked with a shallow `===`, or if the number of elements in `frames` has changed. On top of that, `Plotly.react` itself will only refresh the data being plotted if the identity of the data arrays, the `x`, `y` and `marker.color` values and the like, has changed, or if `layout.datarevision` has changed. The README draws the conclusion in as many words, that simply adding data points to a trace in `data` or changing a value in `layout` will not cause a plot to update unless this is done immutably, with immutability-helper named as an option if performance considerations permit, or unless `revision` and `layout.datarevision` are used to force a rerender. In other words, a chart fed from a mutable array in your Redux store will look frozen, and the fix is to produce new array identities, which is the opposite of what most React code does by default.

The prop surface, including the warning about mutation

The API reference lists a compact set of props. `data` defaults to an empty array, `layout`, `frames` and `config` are undefined by default, and `revision` is a number that, when provided, causes the plot to update when it is incremented. The callbacks are the interesting ones. `onInitialized` and `onUpdate` both receive the figure and the graph div, `onPurge` is executed when the component unmounts, before `Plotly.purge` strips the graph div of all its private attributes, and `onError` is called when a plotly.js API method rejects, and it receives the error. Above the table there is a warning that deserves attention, because it is a known deviation from React's rules. The README says that for the time being the component may mutate its `layout` and `data` props in response to user input, going against React rules, and that this behaviour will change in the near future once the referenced plotly.js issue is completed. So a component that renders a figure and also receives updates to that same figure is currently living in a world where the props can change underneath it.

Beyond the basic component

The README's contents list points at several features beyond the happy path, and each solves a real problem. Responsive plots and event handlers are the everyday needs, and there are separate sections for them, plus a section on TypeScript and one on grabbing the graph div through a ref, which is how you reach the underlying plotly.js instance when you need a method the component does not expose. Two sections are about deployment rather than usage. One covers customizing the plotly.js bundle, which matters because plotly.js is large and shipping all of it when you use two chart types is wasteful, and the other covers loading from a `<script>` tag, for the case where the charting library is already on the page and you do not want to bundle it. The package manifest also exposes a `./factory` export path alongside the main entry, which is the mechanism for building your own component with a preset configuration rather than passing everything through props on every call.

How it is built and published

The package is built with tsup, with a `tsup.config.mjs` in the repository, and the manifest is careful about module formats. It is a commonjs package with `sideEffects` set to false, it requires Node 18 or later, and it publishes a CommonJS build as `main`, an ES module build as `module`, type declarations as `types`, and separate declaration files for the ESM and CJS entry points inside the exports map, with the `./factory` subpath getting the same treatment. It also publishes a standalone browser bundle for unpkg and jsdelivr, which is what makes the script tag route work without a bundler. Only `dist` is published. The test script is a pipeline, and it runs lint and typecheck before jest, so a type error fails the test run rather than being discovered later. Linting is prettier for formatting and eslint for the rules, with a flat config, and there is a watch mode for both the test run and the build.

The release rhythm and what a major version meant

The release history is compressed, with 3.0.0 on 2026-06-09, 4.0.0 on 2026-06-18 and 4.1.0 on 2026-07-29, and the last push was on 2026-09-16, so the project is being worked on and shipping quickly. The jump from 3 to 4 within nine days is worth a note for anyone upgrading, since a major version in a React component usually means either a breaking API change or a deliberate dependency bump, and the README's contents list shows that the component now has a factory export, dual module formats and a maintained-by-Plotly badge, all of which arrived around that time. The repository also carries a `CHANGELOG.md` and a `RELEASE.md`, which is where a reader upgrading from 3.x should look first, along with a code of conduct. The licence is MIT and the author field names Plotly, Inc., and the project carries the Plotly maintained badge, which is the strongest signal here that this is a first party component rather than a community wrapper.

Editorial conclusion

Adopt react-plotly.js if you are rendering Plotly charts inside React and you want the full plotly.js API rather than a subset, and if you are prepared to hold the figure state in your own component. Do not adopt it expecting a stateful chart component, because the README is explicit that it does not merge its internal state with your updates, and the cost of that design is that you have to upstream user interactions yourself. Before you adopt it, read the refresh rules, since data is only redrawn when the identity of a trace array changes, and a chart that mutates a value in place will silently not update. Also check the mutation warning, because the component may currently mutate your `data` and `layout` props in response to user input against React's rules, and the README says that behaviour is due to change. The licence is MIT, the current release is 4.1.0 from 2026-07-29, and the last push was on 2026-09-16.

Frequently asked questions

Why does my react-plotly.js chart not update when the data changes?

The component refreshes through `Plotly.react` only if the `revision` prop changed, or if `data`, `layout` or `config` changed identity under a shallow `===`, or if the number of `frames` elements changed. Plotly.react then only redraws the plotted data if the identity of the data arrays changed or `layout.datarevision` changed, so mutating a trace in place does not update the plot and the data has to be produced immutably.

How do I keep the zoom and pan state of a react-plotly.js chart?

Hold the figure in your own state and wire `onUpdate` to it, as the README's example does with `useState` and both `onInitialized` and `onUpdate` set to the same setter. The component is a dumb component that does not merge its internal state with your updates, so user interactions are lost on the next re-render unless you capture them.

Does react-plotly.js mutate my props?

The README carries a warning that for the time being the component may mutate its `layout` and `data` props in response to user input, going against React rules, and that the behaviour will change once the referenced plotly.js issue is completed. `onPurge` runs on unmount before `Plotly.purge` strips the graph div of its private attributes.

How do I install react-plotly.js and how is it published?

With `npm install react-plotly.js plotly.js`, since the component and the library it wraps are separate packages. The published package is MIT licensed, requires Node 18 or later, ships CommonJS and ES module builds with type declarations for both, is marked side effect free, and also publishes a standalone browser bundle for unpkg and jsdelivr.

Official sources

  1. Issues
  2. License: MIT
  3. plotly/react-plotly.js on GitHub
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/plotly-react-plotly-js.svg)](https://hysenlabs.com/projects/plotly-react-plotly-js)

Was this useful?