Javascript 使用setInterval定期追加新数据时Recharts图表不更新
我正在尝试设置一个网页,每2分钟在折线图上添加一个分数,但它似乎不起作用 我使用的图表是Recharts中的折线图,scoreData的初始值是一个空列表,{time}的初始形式是{h:0,m:0,s:0} 我正在使用上下文和挂钩,这样即使用户出于某种原因临时访问我将创建的其他页面,页面也不会停止计数 我写下的代码如下:Javascript 使用setInterval定期追加新数据时Recharts图表不更新,javascript,reactjs,recharts,Javascript,Reactjs,Recharts,我正在尝试设置一个网页,每2分钟在折线图上添加一个分数,但它似乎不起作用 我使用的图表是Recharts中的折线图,scoreData的初始值是一个空列表,{time}的初始形式是{h:0,m:0,s:0} 我正在使用上下文和挂钩,这样即使用户出于某种原因临时访问我将创建的其他页面,页面也不会停止计数 我写下的代码如下: const Timer = () => { const { scoreData, setScoreData, time, setTim
const Timer = () => {
const {
scoreData,
setScoreData,
time,
setTime,
interv,
setInterv,
} = useContext(BaseContext);
const addNewData = () => {
setScoreData([...score, {Some New data}])
}
const start = () => {
run();
setInterv(setInterval(run, 1000));
};
var updatedS = time.s,
updatedM = time.m,
updatedH = time.h;
const run = () => {
updatedS++;
if (updatedS === 60) {
updatedM++;
updatedS = 0;
if (updatedM % 2 == 0) {
addNewData();
console.log(scoreData.length);
}
}
if (updatedM === 60) {
updatedH++;
updatedM = 0;
}
return setTime({
s: updatedS,
m: updatedM,
h: updatedH,
});
};
return (
<div>
// The code of the line chart goes in here.
<button onClick={start}>Start</button>
<button onClick={addNewData}>Test Button</button>
</div>
)
const Timer=()=>{
常数{
分数数据,
核心数据,
时间
设定时间,
interv,
塞特涅夫,
}=useContext(BaseContext);
const addNewData=()=>{
setScoreData([…分数,{一些新数据}])
}
常量开始=()=>{
run();
setInterv(setInterval(运行,1000));
};
var updatedS=time.s,
updatedM=time.m,
updatedH=时间.h;
常量运行=()=>{
updatedS++;
如果(更新次数===60){
edm++;
updatedS=0;
如果(updatedM%2==0){
addNewData();
console.log(scoreData.length);
}
}
如果(updatedM==60){
更新的h++;
updatedM=0;
}
返回设定时间({
s:更新,
m:,
h:更新了,
});
};
返回(
//折线图的代码在这里。
开始
测试按钮
)
根据上面的代码,每两分钟应该向列表中添加一个新数据,但图表从未显示任何更改
当我使用console.log(scoreData.length)确认scoreData的状态时,控制台只显示了0,这意味着数据没有附加到列表中
因此,我尝试了一种不同的方法,制作了一个测试按钮,手动添加新数据,效果很好;每次按下该按钮,列表中都充满了新数据
在这种情况下,如何使图表根据我设置的时间周期性地接收数据?我假设
setScoreData([…score,{Some New data}])
应该是setScoreData([…scoreData,{Some New data}])
您的setInterval
接收到一个带有固定scoreData
的闭包,并不断调用它。因此setcoredata([…scoreData,{Some New data}])
总是设置相同的数据。
在您的情况下,最好使用hook解决此问题:
Test按钮之所以有效,是因为它在每次渲染时都会得到一个新的闭包。Ciao,不幸的是,对于react钩子,您不能以使用它的方式使用它。问题与钩子本身有关。根据您的代码示例,您希望每秒向
scoreData
添加一个新数据。因此,您可以调用useInterv启动run
的所有if(updateedm%2==0)
调用addNewData
,最终为您的分数数据添加值
不幸的是,对于挂钩,您不确定是否已使用您在previuossetInterval
中添加的数据更新了scoreData
。为什么?因为挂钩是异步的
如何解决这个问题?使用另一个钩子,特别是自定义钩子
一个有效的例子。
让我们看看我的自定义钩子useInterval
:
function useInterval(callback, delay) {
const savedCallback = useRef();
// Remember the latest callback.
useEffect(() => {
savedCallback.current = callback;
}, [callback]);
// Set up the interval.
useEffect(() => {
function tick() {
savedCallback.current();
}
if (delay !== null) {
let id = setInterval(tick, delay);
return () => clearInterval(id);
}
}, [delay]);
}
正如您在我的自定义钩子中所看到的,我使用2useffect
:1来记住最新的useInterval
回调(使用useRef
),另一个用于设置setInterval
的延迟(最后一个useffect
返回一个clearInterval
以取消最后一个setInterval
)
然后我可以在我的组件中调用useInterval
:
useInterval(() => {
if (sampling) {
let result = _.cloneDeep(list1);
result.push({
x: Math.floor(Math.random() * 100),
y: Math.floor(Math.random() * 100)
});
console.log(result);
setlist1(result);
}
}, 1000);
list1
是我的值数组(你的scoreData
),而sampling
是一个bool状态变量,我使用它来运行/停止将新值插入list1
最后,我的返回
:
return (
<div>
<ScatterChart
width={600}
height={400}
margin={{ top: 20, right: 20, bottom: 20, left: 20 }}
>
<CartesianGrid />
<XAxis type="number" dataKey={"x"} />
<YAxis type="number" dataKey={"y"} />
<Tooltip cursor={{ strokeDasharray: "3 3" }} />
<Legend />
<Scatter
name="values"
data={list1}
fill="#8884d8"
line
shape="circle"
/>
</ScatterChart>
<button onClick={start}>
{sampling ? "Stop sampling" : "Start sampling"}
</button>
</div>
);
返回(
{采样?“停止采样”:“开始采样”}
);
我使用了散点图
(在图形上等于折线图
)和一个按钮来启动/停止数据采样。非常感谢您的帮助!我完全不了解挂钩和异步系统,但由于您的透彻解释,我想我离反应系统更近了一点:)很高兴听到这个消息!祝您愉快:)谢谢您的帮助!我尝试了代码,看到图表不时更新,但是当我将console.log(scoreData)放在addNewData函数中时,控制台显示了一个空列表。不确定为什么在可以清楚地看到图表更新时会出现这种情况。。。
return (
<div>
<ScatterChart
width={600}
height={400}
margin={{ top: 20, right: 20, bottom: 20, left: 20 }}
>
<CartesianGrid />
<XAxis type="number" dataKey={"x"} />
<YAxis type="number" dataKey={"y"} />
<Tooltip cursor={{ strokeDasharray: "3 3" }} />
<Legend />
<Scatter
name="values"
data={list1}
fill="#8884d8"
line
shape="circle"
/>
</ScatterChart>
<button onClick={start}>
{sampling ? "Stop sampling" : "Start sampling"}
</button>
</div>
);