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

react-chartjs-2折线图无法随组件状态更新,求解决方案

React-chartjs-2 Line Chart Not Updating with State in Electron Project

我在Electron项目中使用react-chartjs-2的Line组件时遇到了一个问题:当组件状态更新时,折线图不会跟着刷新,但其他类型的图表都能正常更新。尝试给图表组件添加key={Math.random()}虽然能让图表更新,但会导致整个折线图重新渲染,这不是我想要的效果。以下是我的代码:

import React, { Component } from "react";
import { Line, Chart } from "react-chartjs-2"
import { ipcRenderer } from "electron"

class Network extends Component {
  state = {
    data : {
      networkUpload : [0, 0, 0, 0, 0],
      networkDownlaod : [0, 0, 0, 0, 0]
    }
  }

  constructor(props){
    super(props);
    ipcRenderer.send("get-dynNet-data")
  }

  componentDidMount(){
    let data = {...this.state.data};
    ipcRenderer.on('network-data', (e, newData)=>{
      data.networkUpload.splice(0, 1);
      data.networkUpload.push(newData.networkUpload);
      data.networkDownlaod.splice(0, 1)
      data.networkDownlaod.push(newData.networkDownlaod);
      this.setState({data});
    });
  }

  componentWillUnmount(){
    ipcRenderer.removeAllListeners();
  }

  // Decide Weather to show transfer rate in KBPS (kilobytes per sec) or MBPS (megabytes per sec)
  transferRate (dataRate){
    let lastData = dataRate[dataRate.length - 1];
    if(lastData > 1024){
      let mbps = lastData / 1024;
      return `${mbps} Mbps`;
    }else{
      return `${lastData} Kbps`;
    }
  }

  render() {
    // Data for Line Chart "data" props
    let options = {
      labels : ["5 sec", "4 sec", "3 sec", "2 sec", "1 sec"],
      datasets:[{
        label : "Download",
        backgroundColor : 'rgba(255, 99, 132, 1)',
        data : this.state.data.networkDownlaod,
        fill : false
      }, {
        label : "Upload",
        backgroundColor : 'rgba(255, 205, 86, 1)',
        data : this.state.data.networkUpload,
        fill : false
      }],
    }

    // Static data for LineChart "option" props
    let axisOptions = {
      scales: {
        yAxes: [{
          display: true,
          ticks: {
            // suggestedMin: 0, // minimum will be 0, unless there is a lower value.
            suggestedMax: 10, // OR
            // beginAtZero: true, // minimum value will be 0.
          }
        }]
      },
      maintainAspectRatio: false
    }

    // Legend Visibility
    let legend = {
      display: true
    }

    return (
      <div>
        <h3 className="text-grey text-center">NETWORK USAGE</h3>
        <Line width={5} height={150} data={options} legend={legend} className="network-chart" options={axisOptions} />
        <h6 className="net-upload text-grey clearfix">Upload : {this.transferRate(this.state.data.networkUpload)}</h6>
        <h6 className="net-download text-grey">Download : {this.transferRate(this.state.data.networkDownlaod)}</h6>
      </div>
    );
  }
}

export default Network;

问题原因

react-chartjs-2的Line组件在判断是否需要更新图表时,是基于数据引用的浅比较。你的代码中直接修改了state里的原数组(用splice和push操作),这会导致数组的引用没有发生变化——React和react-chartjs-2都会认为数据没有更新,因此不会触发图表的重绘。

解决方案

解决的核心是:不要直接修改原状态中的数组,而是创建新的数组副本,这样就能让组件检测到数据引用的变化,从而更新图表,同时避免全量重渲染。

修改你的componentDidMount方法中的数据更新逻辑:

componentDidMount(){
  ipcRenderer.on('network-data', (e, newData)=>{
    // 对上传数据数组做处理:移除第一个元素,添加新数据,生成新数组
    const updatedUpload = [...this.state.data.networkUpload.slice(1), newData.networkUpload];
    // 对下载数据数组做同样处理
    const updatedDownload = [...this.state.data.networkDownlaod.slice(1), newData.networkDownlaod];
    
    // 更新state,使用全新的data对象和数组
    this.setState({
      data: {
        ...this.state.data,
        networkUpload: updatedUpload,
        networkDownlaod: updatedDownload
      }
    });
  });
}

额外提示

  1. 注意到你代码里的networkDownlaod有拼写错误(应该是networkDownload),虽然不影响当前功能,但建议修正,避免后续维护时出现混淆。
  2. 如果你的Chart.js版本是v3及以上,axisOptions中的yAxes配置需要调整为scales.y(旧版本的yAxes在v3中已经被移除),不过这和当前图表不更新的问题无关,只是一个兼容性提示。

这样修改后,折线图会在状态更新时平滑地更新数据,而不会重新渲染整个组件。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 05:12:55