3

I'm using REACT-PLOTLY.JS to create a scatter graph. I've got everything working apart from the graph redrawing it self every-time I change a data point when using a list of objects in the array data prop. BUT... when I manually write the array and it's containing objects, my graph does not re-draw when I change a data point, which is how it should work. The 2nd solution is not dynamic and is unusable. Can anyone help please?

re-draws graph when data point changes.

<Plot
                data={plotlyData}

does not re-draw graph when data point is changed but is not dynamic and therefore unusable.

<Plot
                data={[plotlyData[0],plotlyData[1]]}

I'm using functional components.

How plotData is generated. I'm using an API to get the coordinates for the X and Y axis.

import { React, useState } from "react";
import Plot from "react-plotly.js";
import { useQuery } from "react-query";
import axios from "axios";

const PlotlyGraph = (props) => {
    const [plot, setPlot] = useState([]);///not in use
    const { datasets } = props;

    const QueryUuid = datasets.map((d) => {
        // console.log("Individual Dataset:", d);
        return `${d.age}-${d.kmax}-${d.frontK}-${d.pachymetry}`;
    });
    const { error, isLoading, data } = useQuery(
        `data-${QueryUuid.join("-")}`,
        () =>
            axios.post("/api/calculate_cxl", {
                age_baseline: datasets.map((d) => d.age),
                kmax: datasets.map((d) => d.kmax),
                front_k1: datasets.map((d) => d.frontK),
                tpt2: datasets.map((d) => d.pachymetry),
                color: datasets.map((d) => d.color),
            })
    );

    let plotlyData;
    if (error !== null || isLoading === true) {
        plotlyData = [];
    } else {
        plotlyData = data.data.map((d, i) => {
            return {
                x: d.x,
                y: d.y,
                type: "scatter",
                mode: "lines",
                marker: { color: datasets[i].color },
                line: {
                    width: 3,
                },

                name: `Patient ${i + 1}`,
                showlegend: true,
            };
        });
    }

    console.log("plot:", plotlyData);

    //- Graph Configuration
    const config = {
        editable: false,
        scrollZoom: true,
        displayModeBar: true,
        displaylogo: false,
    };

    return (
        <>
            <Plot
                data={plotlyData}
                layout={{
                    yaxis: { range: [0, 1] },
                    xaxis: { range: [0, 5] },
                    autoSize: "true",
                    title: "Patient Comparison",
                }}
                style={{ width: "100%", height: " 700px" }}
                useResizeHandler={true}
                config={config}
                revision={0}
                // onInitialized={plot}
                // onUpdate={(plot) => setPlot(plotlyData)}
            />
        </>
    );
};

export default PlotlyGraph;

1 Answer 1

1

I had a similar issue and was able to figure out how to dynamically update my plot with new data after every API fetch (see State Management). Since I don't have access to the API you are using, I've included my own example.

From my API, I fetch an object that looks like this:

{
  28AD7D49F6E13C0A: [69.36, 64.11, 68.69, 62.1, ...],
  28DDC649F6003C1C: [69.59, 63.18, 60.63, 63.08, ...],
  Time: ['20:50:15', '20:50:17', '20:50:19', '20:50:21', ...]
}

Every two seconds, that objects gets updated with a new item in each array. When the state data gets updated with setData, the state object gets updated, which then causes the plot to render with new data.

Full example:

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

function TemperatureGraph() {
  const [data, setData] = useState({});

  const state = {
    data: [
      {
        x: data["Time"],
        y: data["28AD7D49F6E13C0A"],
        name: "28AD7D49F6E13C0A",
        type: "scatter",
        mode: "lines+markers",
        marker: {
          color: "red",
        },
      },
      {
        x: data["Time"],
        y: data["28DDC649F6003C1C"],
        name: "28DDC649F6003C1C",
        type: "scatter",
        mode: "lines+markers",
        marker: {
          color: "black",
        },
      },
    ],
    layout: {
      width: 800,
      height: 500,
      title: "",
      xaxis: {
        title: "Time",
      },
      yaxis: {
        title: "Temperature (F)",
      },
    },
    frames: [],
    config: {},
  };

  useEffect(() => {
    const timer = setInterval(() => {
      fetch("/get-temperatures")
        .then((response) => response.json())
        .then((data) => setData(data));
    }, 2000);
    return () => clearInterval(timer);
  }, []);

  return (
    <div>
      <Plot data={state.data} layout={state.layout} />
    </div>
  );
}

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

Comments

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.