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

如何使用Highcharts React库动态更新市场深度图表数据?

问题:Highcharts React 市场深度图表无法实时更新数据

我已成功使用Highcharts React组件将表格中的数据绘制为市场深度图表,但存储买盘(bids)和卖盘(asks)数据的数组会持续更新,当前图表仅能通过刷新页面同步数据。

现有代码

class MarketDepth extends React.Component<Props, State> {

   ...

    chart = null;

    state = {
        selectedBid: null,
        selectedAsk: null,
    };

    chartOptions = {
        chart: {
            type: 'area',
            zoomType: 'xy',
        },

        title: {
            text: 'Market Depth Chart',
            style: {
                color: '#FFFFFF',
                fontSize: '20px',
                lineHeight: '120%',
                fontWeight: '600',
            },
        },
        xAxis: {
            minPadding: 0,
            maxPadding: 0,
            crosshair: true,
            lineWidth: 0,
            gridLineWidth: 0,
            tickLength: 4,
            plotLines: [
                {
                    color: '#FFFFFF',
                    width: 1,
                    value: this.getAverageLine(), // 设置实际价格线数值
                    label: {
                        text: 'Actual price',
                        rotation: 90,
                        align: 'right',
                        style: {
                            fonstStyle: 'italic', // 存在拼写错误
                        },
                    },
                },
            ],
            title: {
                text: 'Price',
            },
        },
        yAxis: [
            {
                crosshair: true,
                lineWidth: 0,
                gridLineWidth: 0,

                title: {
                    text: 'Acc',
                },
                tickWidth: 1,
                tickLength: 5,
                tickPosition: 'inside',
                labels: {
                    align: 'left',
                    x: 8,
                },
            },
            {
                opposite: true,
                linkedTo: 0,
                lineWidth: 0,
                gridLineWidth: 0,
                title: {
                    text: 'Acc',
                },
                tickWidth: 1,
                tickLength: 5,
                tickPosition: 'inside',
                labels: {
                    align: 'right',
                    x: -8,
                },
            },
        ],
        legend: {
            enabled: false,
        },
        plotOptions: {
            area: {
                states: {
                    hover: {
                        enabled: false,
                        lineWidthPlus: 0,
                    },
                    inactive: {
                        opacity: 1,
                    },
                },
                marker: { enabled: false },
                fillOpacity: 0.2,
                lineWidth: 1,
                step: 'center',
            },
        },
        tooltip: {
            headerFormat: '<span style="font-size=10px;">Price: {point.key}</span><br/>',
            valueDecimals: 2,
        },
        series: [
            {
                name: 'Bids',
                data: this.getBidOrders(),
                step: 'left',
            },
            {
                name: 'Asks',
                data: this.getAskOrders(),
                color: '#fc5857',
                step: 'right',
            },
        ],
    };

    getBidOrders() {
        ...
    }

    getAskOrders() {
        ... 
    }

   ...

   render() {
      return (
          <div id='chartContainer'>
                <HighchartsReact
                    highcharts={Highcharts}
                    options={this.chartOptions}
                    allowChartUpdate
                />
          </div>
      )
   }
}

数据格式示例

getAskOrders()和getBidOrders()返回的二维数组格式:

[
    [2179.25, 30],
    [2179, 70],
    [2178.75, 113],
    [2178.5, 159],
    [2178.25, 206]
]

已尝试方案

  • 使用React useState钩子管理chartOptions的状态
  • 尝试利用chartOptions中的events属性更新图表值

解决方案

方法1:通过React状态管理动态更新配置

将chartOptions放入组件状态,当数据更新时重新生成配置并更新状态,触发组件重渲染,Highcharts React会自动同步图表:

class MarketDepth extends React.Component<Props, State> {
  chart = null;
  state = {
    selectedBid: null,
    selectedAsk: null,
    chartOptions: {} // 初始化空配置
  };

  componentDidMount() {
    // 挂载时初始化图表配置
    this.setState({ chartOptions: this.getChartOptions() });
    // 这里可以添加数据更新监听(如WebSocket)
    // this.setupDataListener();
  }

  componentDidUpdate(prevProps) {
    // 当props中的买卖盘数据变化时,更新图表配置
    if (prevProps.bids !== this.props.bids || prevProps.asks !== this.props.asks) {
      this.setState({ chartOptions: this.getChartOptions() });
    }
  }

  getChartOptions() {
    return {
      chart: {
        type: 'area',
        zoomType: 'xy',
      },
      title: {
        text: 'Market Depth Chart',
        style: {
          color: '#FFFFFF',
          fontSize: '20px',
          lineHeight: '120%',
          fontWeight: '600',
        },
      },
      xAxis: {
        minPadding: 0,
        maxPadding: 0,
        crosshair: true,
        lineWidth: 0,
        gridLineWidth: 0,
        tickLength: 4,
        plotLines: [
          {
            color: '#FFFFFF',
            width: 1,
            value: this.getAverageLine(),
            label: {
              text: 'Actual price',
              rotation: 90,
              align: 'right',
              style: {
                fontStyle: 'italic', // 修正拼写错误
              },
            },
          },
        ],
        title: {
          text: 'Price',
        },
      },
      yAxis: [
        {
          crosshair: true,
          lineWidth: 0,
          gridLineWidth: 0,
          title: {
            text: 'Acc',
          },
          tickWidth: 1,
          tickLength: 5,
          tickPosition: 'inside',
          labels: {
            align: 'left',
            x: 8,
          },
        },
        {
          opposite: true,
          linkedTo: 0,
          lineWidth: 0,
          gridLineWidth: 0,
          title: {
            text: 'Acc',
          },
          tickWidth: 1,
          tickLength: 5,
          tickPosition: 'inside',
          labels: {
            align: 'right',
            x: -8,
          },
        },
      ],
      legend: {
        enabled: false,
      },
      plotOptions: {
        area: {
          states: {
            hover: {
              enabled: false,
              lineWidthPlus: 0,
            },
            inactive: {
              opacity: 1,
            },
          },
          marker: { enabled: false },
          fillOpacity: 0.2,
          lineWidth: 1,
          step: 'center',
        },
      },
      tooltip: {
        headerFormat: '<span style="font-size=10px;">Price: {point.key}</span><br/>',
        valueDecimals: 2,
      },
      series: [
        {
          name: 'Bids',
          data: this.getBidOrders(),
          step: 'left',
        },
        {
          name: 'Asks',
          data: this.getAskOrders(),
          color: '#fc5857',
          step: 'right',
        },
      ],
    };
  }

  getBidOrders() {
    // 从props或内部状态获取最新买盘数据
    return this.props.bids || [];
  }

  getAskOrders() {
    // 从props或内部状态获取最新卖盘数据
    return this.props.asks || [];
  }

  // 示例:设置数据更新监听
  // setupDataListener() {
  //   // 假设通过WebSocket获取实时数据
  //   const ws = new WebSocket('your-data-endpoint');
  //   ws.onmessage = (event) => {
  //     const { bids, asks } = JSON.parse(event.data);
  //     // 更新props(如果用Redux或父组件传值)或内部状态
  //     this.props.updateMarketData(bids, asks);
  //   };
  // }

  render() {
    return (
      <div id='chartContainer'>
        <HighchartsReact
          highcharts={Highcharts}
          options={this.state.chartOptions}
          allowChartUpdate={true}
        />
      </div>
    );
  }
}

方法2:直接操作Highcharts实例更新数据

通过ref获取图表实例,直接调用Highcharts API更新系列数据,性能更优,避免组件重渲染:

class MarketDepth extends React.Component<Props, State> {
  chartRef = React.createRef();
  state = {
    selectedBid: null,
    selectedAsk: null,
    interval: null
  };

  componentDidMount() {
    // 启动数据更新监听
    this.setupDataListener();
  }

  setupDataListener() {
    // 模拟实时数据更新(实际项目替换为WebSocket等)
    const interval = setInterval(() => {
      const newBids = this.getBidOrders();
      const newAsks = this.getAskOrders();
      this.updateChart(newBids, newAsks);
    }, 2000);

    this.setState({ interval });
  }

  componentWillUnmount() {
    // 组件卸载时清除定时器
    if (this.state.interval) clearInterval(this.state.interval);
  }

  updateChart(newBids, newAsks) {
    const chart = this.chartRef.current?.chart;
    if (!chart) return;

    // 更新买盘数据,第二个参数设为false避免多次重绘
    chart.series[0].setData(newBids, false);
    // 更新卖盘数据,第二个参数设为true完成重绘
    chart.series[1].setData(newAsks, true);

    // 同步更新平均价格线
    chart.xAxis[0].update({
      plotLines: [{
        color: '#FFFFFF',
        width: 1,
        value: this.getAverageLine(),
        label: {
          text: 'Actual price',
          rotation: 90,
          align: 'right',
          style: {
            fontStyle: 'italic',
          },
        },
      }]
    });
  }

  // 原图表配置保持不变
  chartOptions = { /* ... 原配置内容 ... */ };

  getBidOrders() {
    ...
  }

  getAskOrders() {
    ...
  }

  render() {
    return (
      <div id='chartContainer'>
        <HighchartsReact
          highcharts={Highcharts}
          options={this.chartOptions}
          ref={this.chartRef}
          allowChartUpdate={true}
        />
      </div>
    );
  }
}

关键注意事项

  • 原代码中chartOptions是类的静态属性,不会随数据更新重新生成,必须让配置动态生成或直接操作实例。
  • 修正了原代码中fonstStyle的拼写错误,改为fontStyle。
  • 确保allowChartUpdate={true}(默认值为true,显式声明更清晰),允许Highcharts React更新图表。

内容的提问来源于stack exchange,提问作者Andrei Călugăr

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 05:17:34