我正在尝试设置一个网页,每 2 分钟在折线图上添加一个分数,但它似乎不起作用。
我使用的图表是来自 Recharts 的折线图,scoreData 的初始值为空列表,{time} 的初始形式为 {h:0, m:0, s:0}。
我正在使用上下文和挂钩,以便即使用户出于某种原因暂时访问我将创建的其他页面,页面也不会停止计数。
我写下来的代码如下;
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>
)
根据上面的代码,应该每两分钟向列表添加一个新数据,但图表从未显示任何变化。
当我使用console.log(scoreData.length)确认scoreData的状态时,控制台只显示0,这意味着数据没有被附加到列表中。
所以我尝试了一种不同的方法,通过制作一个手动添加新数据的测试按钮,它工作得很好;每次我推送列表时,列表中都充满了新数据。
在这种情况下,我该怎么做才能让图表按照我设置的时间定期接收数据?
Ciao,不幸的是,对于 React 钩子,你不能setInterval
以你使用它的方式使用它。问题与钩子本身有关。根据您的代码示例,您希望scoreData
每秒向您添加一个新数据。所以你调用useInterval
启动run
那个,if (updatedM % 2 == 0)
调用addNewData
最终为你的scoreData
.
不幸的是,对于钩子,您不确定scoreData
是否已经使用您在 previuos 中添加的数据进行了更新setInterval
。为什么?因为钩子是异步的!
如何解决这个问题?用另一个钩子,特别是一个定制的钩子!
这是一个工作示例。让我们看看我的自定义钩子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]);
}
正如您在我的自定义钩子中看到的,我使用 2 useEffect
: 1 来记住最新的useInterval
回调(使用useRef
);另一个用于设置延迟setInterval
(这最后一个useEffect
返回一个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
是一个布尔状态变量,我用来运行/停止向list1
.
最后,我的return
:
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>
);
我使用ScatterChart
(图形上等于LineChart
)和一个按钮来开始/停止数据采样。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句