You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React-Redux集成chartjs-plugin-streaming折线图无法显示后续数据

问题原因
  • 随机数生成逻辑仅执行1次:你将generateRngNum的dispatch放在了仅依赖dispatch(引用永久不变)的useEffect中,只会在组件首次挂载时触发一次,后续图表每5秒刷新时不会生成新随机数,Redux中永远只存第一个生成的值。
  • 图表数据集被反复重置:data配置对象直接写在组件函数体内,每次组件因Redux状态更新重渲染时,三个数据集的data数组都会被重新初始化为空,之前推入的所有数据点直接丢失。
  • 闭包陷阱:onRefresh回调永久捕获组件第一次渲染时拿到的coTwoData值,后续Redux更新的新数据无法被回调读取,就算生成新值也拿不到。
  • 逻辑脱节:chartjs-plugin-streaming本身会按配置的refresh间隔定时触发onRefresh,你没有把新数据生成逻辑绑定到这个回调上,无法和图表刷新同步。
修复方案
  1. 移除组件首次加载时触发dispatch的useEffect,把随机数生成逻辑移到onRefresh回调内,保证每次图表刷新都生成新值。
  2. 用useMemo持久化图表data配置对象,避免重渲染时重置数据集数组。
  3. 用useRef存储最新的Redux数据,解决onRefresh的闭包陷阱,保证回调能拿到最新生成的值。

修改后主组件代码

import { coTwoActions } from "../../store/redux";
import { useDispatch, useSelector } from "react-redux";

import React, { useEffect, useMemo, useRef } from "react";
import "chart.js/auto";
import "./chartLiveData.css";
import plugins from "../Settings/plugins";
import { Line } from "react-chartjs-2";
import { Chart } from "chart.js";
import ChartStreaming from "chartjs-plugin-streaming";
import "chartjs-adapter-luxon";
import Zoom from "chartjs-plugin-zoom";

Chart.register(Zoom);
Chart.register(ChartStreaming);

const ChartLiveDataReduxV3 = () => {
  const dispatch = useDispatch();
  // 持久化图表配置,避免重渲染重置数据集
  const data = useMemo(() => ({
    datasets: [
      {
        label: "400-1000 ppm",
        data: [],
        fill: false,
        backgroundColor: "rgba(0, 255, 0, 0.5)",
        showLine: false,
        pointStyle: "circle",
        pointRadius: 5,
        pointHoverRadius: 10,
      },
      {
        label: "1001-2000 ppm",
        data: [],
        fill: false,
        backgroundColor: "rgba(255, 255, 0, 0.5)",
        showLine: false,
        pointStyle: "circle",
        pointRadius: 5,
        pointHoverRadius: 10,
      },
      {
        label: "2001 + ppm",
        data: [],
        fill: false,
        backgroundColor: "rgba(255, 0, 0, 0.5)",
        showLine: false,
        pointStyle: "circle",
        pointRadius: 5,
        pointHoverRadius: 10,
      },
    ],
  }), []);

  const coTwoData = useSelector((state) => state.coTwoData);
  // 用ref存储最新数据,解决闭包问题
  const coTwoDataRef = useRef(coTwoData);
  useEffect(() => {
    coTwoDataRef.current = coTwoData;
  }, [coTwoData]);

  const onRefresh = () => {
    // 每次刷新先生成新随机数
    dispatch(coTwoActions.generateRngNum());
    const latestData = coTwoDataRef.current;
    const latestValue = latestData[latestData.length - 1];
    if (!latestValue) return;
    const { x, y } = latestValue;

    // 按数值区间推入对应数据集
    if (y <= 1000) {
      data.datasets[0].data.push({x, y});
    } else if (y <= 2000) {
      data.datasets[1].data.push({x, y});
    } else {
      data.datasets[2].data.push({x, y});
    }
  };

  const options = {
    scales: {
      x: {
        title: {
          display: true,
          text: "Real-Time",
        },
        type: "realtime",
        realtime: {
          duration: 60000, // 图表展示最近60秒数据
          refresh: 5000, // 5秒刷新一次
          delay: 1000,
          pause: false,
          onRefresh: onRefresh,
        },
      },
      y: {
        title: {
          display: true,
          text: "ppm value CO2",
        },
      },
    },
  };

  return (
    <div>
      <h1 className="centered">
        Carbon Dioxide (CO<sub className="sub">2</sub>)
      </h1>
      <div
        className="container container-prop"
        style={{ width: "1000px", margin: "0 auto" }}
      >
        <Line data={data} plugins={plugins} options={options} />
      </div>
    </div>
  );
};
export default ChartLiveDataReduxV3;

你提供的Redux模块代码逻辑正确,基于Immer的状态更新写法符合Redux Toolkit规范,不需要修改。


内容的提问来源于stack exchange,提问作者Antonis Papadakis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 17:42:42