3

I recently read about being able to use Flask and JS <script> tags to plot Plotly figures from Python and wanted to replicate that with React and Flask as the API instead of vanilla JS. Getting the data is fine, but trying to plot it from Python Plotly packed into JSON -> Plotly on React will never work - it just returns a blank white display.

Here's the code for the API on the Flask side (I just used the /plot1 function from this example to test it out; JSON returned fine):

from flask import Flask
import pandas as pd
import json
import plotly
import plotly.express as px

app = Flask(__name__)

@app.route('/chart1')
def chart1():
    df = pd.DataFrame({
        "Fruit": ["Apples", "Oranges", "Bananas", "Apples", "Oranges", "Bananas"],
        "Amount": [4, 1, 2, 2, 4, 5],
        "City": ["SF", "SF", "SF", "Montreal", "Montreal", "Montreal"]
    })

    fig = px.bar(df, x="Fruit", y="Amount", color="City", barmode="group")
    graphJSON = json.dumps(fig, cls=plotly.utils.PlotlyJSONEncoder)
    return graphJSON

Here's my App.js:

import React, { useState, useEffect } from 'react';
import Plotly from 'plotly.js-dist-min';
import logo from './logo.svg';
import './App.css';

function App() {

  const [plot, setPlot] = useState(0);

  useEffect(() => {
    fetch('/plot').then(res => res.json()).then(data => {setPlot(data);});}, []);

  Plotly.newPlot("graph-div", plot, {})

  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <div id="graph-div" className="graph-div">
        </div>
      </header>
    </div>
  );
}

It seems like there's some sort of problem when receiving the data, but I'm not sure what exactly is wrong - I followed the same format as a React-Flask tutorial when receiving the data and plotted it exactly as the Flask-Plotly example did. Could someone please let me know how to fix this issue?

2 Answers 2

8

I'd like to update this post for anyone interested - I was able to get the Plotly chart to display.

Turns out that the data was not being sent correctly using the json.dumps function. Instead, use the plot to JSON function provided by Plotly.

Updated Code:

api.py:

import time, json
from flask import Flask
import pandas as pd
import plotly
import plotly.express as px

app = Flask(__name__)

@app.route('/time')
def get_current_time():
    return {'time': time.time()}
    
@app.route('/plot')
def plot_test():
    df = pd.DataFrame({
        "Fruit": ["Apples", "Oranges", "Bananas", "Apples", "Oranges", "Bananas"],
        "Amount": [4, 1, 2, 2, 4, 5],
        "City": ["SF", "SF", "SF", "Montreal", "Montreal", "Montreal"]
    })
    fig = px.bar(df, x="Fruit", y="Amount", color="City", barmode="group")
    graphJSON = plotly.io.to_json(fig, pretty=True)
    return graphJSON

App.js:

import React, { useState, useEffect } from 'react';
import Plot from 'react-plotly.js';

const Fund = () => {
    const [plot, setPlot] = useState(0);
    
    useEffect(() => {
      fetch('/plot').then(res => res.json()).then(data => {setPlot(data);});}, []);
      // console.log(plot)
    
    return (
      <div className='content'>
      <h1>Current Fund</h1>
      <Plot data={plot.data} layout={plot.layout}/>
      </div>
    );
};

export default Fund;
Sign up to request clarification or add additional context in comments.

Comments

2

I would suggest you to use react-plotly.js (https://plotly.com/javascript/react/) instead of pure plotly.js. You can create plot as React component;

This is example how to create simple plot by react-plotly.js with data and layout from graphJSON.json file.

Content of graphJSON.json file:

{
  "data": [
        {
          "x": [1, 2, 3],
          "y": [2, 6, 3],
          "type": "scatter",
          "mode": "lines+markers",
          "marker": {
              "color": "red"
          }
        },
        {
          "type": "bar", 
          "x": [1, 2, 3], 
          "y": [2, 5, 3]
      }
  ],
  "layout": {
      "title": "A Fancy Plot"
  } 
}

And React file:

import React from 'react';
import ReactDOM from 'react-dom/client';
import Plot from 'react-plotly.js';
import graphJSON from './graphJSON.json';

function App(){
  return(
    <Plot data={json.data} layout={json.layout}/>
  )
}

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <App />
);

You can import directly your JSON file generated by Python script. It is object with arrays that you can use by accesing them like a property. In our example: graphJSON.data (if you want to access data array)

Result:

output from example

2 Comments

Thanks! I will try using React Plotly. However, the figure I intend to is constantly updating though, so it would probably be better to use Flask to deal with that vs. setting up multiple scripts/crons/etc. Is it possible to fetch the data from Flask directly?
I've not been working with Flask yet, but if you want to update chart data constantly use tool like JSON serwer or simmilar API to refresh plot data. React-Plotly supports update events so mayby you will find the answer in documentation.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.