Reputation: 71
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;
Upvotes: 3
Views: 1338
Reputation: 714
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;
Upvotes: 1