Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 使用setInterval定期追加新数据时Recharts图表不更新_Javascript_Reactjs_Recharts - Fatal编程技术网

Javascript 使用setInterval定期追加新数据时Recharts图表不更新

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

我正在尝试设置一个网页,每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>
)
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
,最终为您的
分数数据添加值

不幸的是,对于挂钩,您不确定是否已使用您在previuos
setInterval
中添加的数据更新了
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]);
  }
正如您在我的自定义钩子中所看到的,我使用2
useffect
: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>
  );