我正在开发一个使用react-chartjs-2显示折线图的React组件。每当从 API 收到新数据 (apiData) 时,图表都应更新。我面临的问题是,如果新的 apiData 值与前一个值相同,则图表不会更新或重新渲染。
这是我组件的相关部分:
import React, { useState, useContext, useEffect } from 'react';
import { Line } from 'react-chartjs-2';
import { DataContext } from '../../context/DataContext';
import 'chart.js/auto';
import styled from 'styled-components';
const MAX_DATA_POINTS = 100;
const Container = styled.div`
width: 99%;
height: 100%;
`;
const Graph = ({ apiData, graphLabel }) => {
const { streaming, clearFlag, setClearFlag } = useContext(DataContext);
const [graphData, setGraphData] = useState(() => {
const storedData = sessionStorage.getItem('graphData');
return storedData ? JSON.parse(storedData) : [];
});
const [key, setKey] = useState(0); // new state to track re-renders
useEffect(() => {
if (streaming) {
setGraphData(prevData => {
const newData = [
...prevData,
{ time: new Date().toLocaleTimeString(), data: apiData }
];
// Limit the number of data points to preserve interval
if(newData.length > MAX_DATA_POINTS){
newData.shift();
}
sessionStorage.setItem('graphData', JSON.stringify(newData));
setKey(prevKey => prevKey + 1); // trigger re-render
return [...newData]; // return new array to trigger re-render
});
}
}, [apiData, streaming]);
const dataPoints = {
labels: graphData.map(d => d.time),
datasets: [
{
label: graphLabel,
data: graphData.map(d => d.data),
fill: false,
backgroundColor: '#F3F4F6',
borderColor: '#0077C8',
},
],
};
useEffect(() => {
if (clearFlag) {
setGraphData([]);
sessionStorage.removeItem('graphData');
setClearFlag(false);
}
}, [clearFlag])
const options = {
scales: {
y: {
beginAtZero: true,
max: 1000,
},
},
maintainAspectRatio: false,
animation: {
duration: 0,
},
plugins: {
legend: {
labels: {
font: {
size: 18,
weight: 'bold',
},
color: 'black'
}
}
}
};
return (
<Container>
<Line data={dataPoints} options={options} />
</Container>
);
};
export default Graph;
我只是添加一个时间戳来比较并触发重新渲染。
useEffect(() => {
if (streaming && apiData !== null) {
setGraphData(prevData => {
const newData = [
...prevData,
{ time: new Date().toLocaleTimeString(), data: apiData }
];
// Limit the number of data points to preserve interval
if(newData.length > MAX_DATA_POINTS){
newData.shift();
}
sessionStorage.setItem('graphData', JSON.stringify(newData));
return [...newData]; // return new array to trigger re-render
});
}
}, [apiData, timestamp, streaming]);
再次感谢 stackoverflow。