Plot.ly + React and dynamic data

João Cota
4 min readDec 25, 2018

--

Image from: https://plot.ly/javascript/react/

First, I’ll contextualize what will be used in this article.

Plot.ly is a library commonly used to draw graphs and other web interfaces. It started with Python but now has many other implementations in different programming languages, like JavaScript and R. It also has special implementations to support some popular frameworks, like React and Angular.

For this article, I am using React, a powerful library to make web applications. Simple code and easy components creation make React scalable and robust.

One day a friend ask me for help integrating Plot.ly with React. She is writing some application that consumes an API and she is creating a tool to see this data. At first, I thought the problem was getting used to the way you write code using modern JavaScript, such as using new naming and development patterns, like for example, installing libraries using NPM. So I pointed her to the initial steps and apparently she made some static graphs. But she needed to draw graphs using dynamic data and she didn’t find a solution that worked for her.

So I go into history. I originally looked in the Plot.ly + React documentation, it’s really good, but for initial and simple problems, such as complex interactions or dynamic loading of data, it’s pretty bad or nonexistent.

Let’s code

First, we need to install Node.js, NPM and React. From the command line, we type

npm i -g create-react-app

and wait until it finishes.

Now we can create our React app with

create-react-app myplotlysite

Move into the app folder

cd myplotlysite

and install Plot.ly in your project using NPM

npm i -SE react-plotly.js plotly.js

Let’s start our project

npm start

and see the results on the browser that opens (the default URL is localhost:3000).

Now we create a class for a graph and define the Plotly component

<Plot
graphDiv="graph"
/>

Defining state to control some lines

state = { 
line1: {
x: [-3, -2, -1],
y: [1, 2, 3],
name: 'Line 1'
},
line2: {
x: [1, 2, 3],
y: [-3, -2, -1],
name: 'Line 2'
}
}

Putting the state on graph data:

<Plot
data={[
this.state.line1,
this.state.line2,
]}
graphDiv="graph"
/>

This is what it looks like:

Static graphic using react and plotly

Let create a function to add data on the graph, and link it to a button. The function will add values to the data array and change values of layout.datarevision and revision.

It will look something like this:

increaseGraphic = () => {
const { line1, line2, layout } = this.state;
line1.x.push(this.rand());
line1.y.push(this.rand());
line2.x.push(this.rand());
line2.y.push(this.rand());
this.setState({ revision: this.state.revision + 1 });
layout.datarevision = this.state.revision + 1;
}

Now our class looks like this:

import React from 'react';
import Plot from 'react-plotly.js';
export default class PlotLyGraphic extends React.Component {
state = {
line1: {
x: [-3, -2, -1],
y: [1, 2, 3],
name: 'Line 1'
},
line2: {
x: [1, 2, 3],
y: [-3, -2, -1],
name: 'Line 2'
},
layout: {
datarevision: 0,
},
revision: 0,
}
rand = () => parseInt(Math.random() * 10, 10);
increaseGraphic = () => {
const { line1, line2, layout } = this.state;
line1.x.push(this.rand());
line1.y.push(this.rand());
line2.x.push(this.rand());
line2.y.push(this.rand());
this.setState({ revision: this.state.revision + 1 });
layout.datarevision = this.state.revision + 1;
}
render() {
return (
<div>
<Plot
data={[
this.state.line1,
this.state.line2,
]}
layout={this.state.layout}
revision={this.state.revision}
graphDiv="graph"
/>
</div>
);
}
}

Extra

With simple changes, we can prepare the component to look for data on a web service or consume from time to time from an API. Understanding the React Component Lifecycle is important for this. For example, we can use the componentDidMount call and the function setInterval to call increaseGraph (or your API call) periodically.

componentDidMount() {
setInterval(this.increaseGraph, 1000);
}

The final component is:

import React from 'react';
import Plot from 'react-plotly.js';
export default class PlotEx extends React.Component {
state = {
line1: {
x: [-3, -2, -1],
y: [1, 2, 3],
name: 'Line 1'
},
line2: {
x: [1, 2, 3],
y: [-3, -2, -1],
name: 'Line 2'
},
layout: {
datarevision: 0,
},
revision: 0,
}
componentDidMount() {
setInterval(this.increaseGraphic, 1000);
}
rand = () => parseInt(Math.random() * 10 + this.state.revision, 10);
increaseGraphic = () => {
const { line1, line2, layout } = this.state;
line1.x.push(this.rand());
line1.y.push(this.rand());
if (line1.x.length >= 10) {
line1.x.shift();
line1.y.shift();
}
line2.x.push(this.rand());
line2.y.push(this.rand());
if (line2.x.length >= 10) {
line2.x.shift();
line2.y.shift();
}
this.setState({ revision: this.state.revision + 1 });
layout.datarevision = this.state.revision + 1;
}
render() {
return (<div>
<Plot
data={[
this.state.line1,
this.state.line2,
]}
layout={this.state.layout}
revision={this.state.revision}
graphDiv="graph"
/>
</div>);
}
}

Conclusions

React is a powerful tool to work with interactions on the screen and Plotly is able to create many nice graphs, but unfortunately its documentation fails to have clear of certain interactions. That does not stop it from being able to work with dynamically generated data.

Much obliged @eliasluizjr for the help with text revision.

Post in Portuguese.

--

--