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

React中useState结合WebSocket更新折线图数据失败求助

React函数组件中WebSocket数据无法更新折线图的问题修复

问题根源

  • 直接修改全局变量:你之前直接修改导出的mockLineData全局变量,React不会追踪这种外部修改,自然不会触发组件重渲染。
  • x值生成逻辑完全错误:用setInterval的返回值(定时器ID)作为x轴数据,这根本不是你需要的递增数值,还会创建一堆无用的定时器。
  • 组件状态更新无效:LineChart里导入的data是初始静态值,就算全局变量变了,这个导入值也不会自动更新,setInterval里反复setState(data)相当于重复设置同一个初始值,完全起不到更新作用。

修复后的完整代码

import { useState, useEffect, useRef } from "react";
import { ResponsiveLine } from "@nivo/line";
import { useTheme } from "@mui/material/styles";
import tokens from "../theme/tokens"; // 按你的实际路径调整

const LineChart = ({ isCustomLineColors = false, isDashboard = false }) => {
  const theme = useTheme();
  const colors = tokens(theme.palette.mode);
  // 用组件内部状态维护折线图数据,初始值和之前的mockLineData一致
  const [chartData, setChartData] = useState([
    {
      id: "ИБП Uвх",
      color: tokens("dark").redAccent[200],
      data: [{ x: 0, y: 0 }],
    },
  ]);
  // 用ref追踪x轴递增数值,避免闭包导致的数值不更新
  const xCounterRef = useRef(1);
  // 用ref保存WebSocket实例,防止组件重渲染时重复创建连接
  const wsRef = useRef(null);

  useEffect(() => {
    // 初始化WebSocket连接
    const ws = new WebSocket("ws://localhost:8000");
    wsRef.current = ws;

    ws.onopen = () => {
      console.log("подключился");
    };

    ws.onmessage = (message) => {
      try {
        const jsonParse = JSON.parse(message.data);
        const newValue = jsonParse[0]["value_state"];

        // 用函数式更新状态,确保基于最新数据修改
        setChartData((prevData) => {
          const updatedSeries = [...prevData];
          let updatedPoints = [...updatedSeries[0].data];
          
          // 保持数据点数量不超过50个
          if (updatedPoints.length >= 50) {
            updatedPoints.shift();
          }
          // 添加新数据点,x值自增
          updatedPoints.push({ x: xCounterRef.current, y: newValue });
          xCounterRef.current += 1;

          updatedSeries[0].data = updatedPoints;
          return updatedSeries;
        });
      } catch (error) {
        console.log("Error: ", error);
      }
    };

    // 组件卸载时关闭WebSocket,防止内存泄漏
    return () => {
      ws.close();
    };
  }, []);

  return (
    <ResponsiveLine
      data={chartData}
      theme={{
        axis: {
          domain: {
            line: {
              stroke: colors.grey[100],
            },
          },
          legend: {
            text: {
              fill: colors.grey[100],
            },
          },
          ticks: {
            line: {
              stroke: colors.grey[100],
              strokeWidth: 1,
            },
            text: {
              fill: colors.grey[100],
            },
          },
        },
        legends: {
          text: {
            fill: colors.grey[100],
          },
        },
        tooltip: {
          container: {
            color: colors.primary[500],
          },
        },
      }}
      colors={isDashboard ? { datum: "color" } : { scheme: "nivo" }}
      margin={{ top: 50, right: 110, bottom: 50, left: 60 }}
      enableGridX={false}
      enableGridY={false}
      pointSize={8}
      pointColor={{ theme: "background" }}
      pointBorderWidth={2}
      pointBorderColor={{ from: "serieColor" }}
      pointLabelYOffset={-12}
      useMesh={true}
      legends={[
        {
          anchor: "bottom-right",
          direction: "column",
          justify: false,
          translateX: 100,
          translateY: 0,
          itemsSpacing: 0,
          itemDirection: "left-to-right",
          itemWidth: 80,
          itemHeight: 20,
          itemOpacity: 0.75,
          symbolSize: 12,
          symbolShape: "circle",
          symbolBorderColor: "rgba(0, 0, 0, .5)",
          effects: [
            {
              on: "hover",
              style: {
                itemBackground: "rgba(0, 0, 0, .03)",
                itemOpacity: 1,
              },
            },
          ],
        },
      ]}
    />
  );
};

export default LineChart;

关键改动说明

  • 放弃全局变量,用组件内部状态管理:所有数据更新都通过setChartData触发,React会自动检测状态变化并重新渲染折线图。
  • WebSocket实例用ref保存:避免组件每次重渲染都新建连接,同时在组件卸载时自动关闭连接,防止内存泄漏。
  • 用ref追踪x值:解决了闭包导致的数值不更新问题,确保x值能持续递增。
  • 函数式更新状态:每次更新都基于最新的状态数据修改,避免状态更新滞后的问题。

内容的提问来源于stack exchange,提问作者Michael Shiko

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 07:17:03