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

Highcharts React饼图与柱状图重复渲染问题求助

问题描述

在React项目中使用Highcharts开发图表功能,PieChart组件代码如下:

import React, { useEffect, useRef, useState } from "react";
import * as Highcharts from "highcharts";
import HighchartsReact from "highcharts-react-official";

export const PieChart = (props: any) => {
  const [chartIsLoaded, setChartIsLoaded] = useState(false);
  const series: any = [{
    innerSize: '80%',
    name: props.name,
    colorByPoint: true,
    data: props.chartData
  }]
  useEffect(() => {
    setChartIsLoaded(true);
  }, [])

  const chartComponentRef = useRef<HighchartsReact.RefObject>(null);
  const options: Highcharts.Options = {
    chart: {
        backgroundColor: "#0c0c0c",
        borderColor: "#0c0c0c",
        plotBorderWidth: 0,
        plotShadow: false,
        type: 'pie',
        height: "70%",
    },
    title: {
        style : {
            display : 'none'
          }
    },
    tooltip: {
      pointFormat: '<b>{point.percentage:.1f}%</b>',
      backgroundColor: "#1B1B1B",
      borderColor: "transparent",
      valueDecimals: 2,
      borderRadius: 0,
      style: {
        color: "#fff",
        fontSize: "15px"

      }
    },
    accessibility: {
        point: {
            valueSuffix: '%'
        }
    },
    legend: {
        itemStyle: {color: "#fff", fontWeight: "400", fontFamily: "teragon-sans"}
    },
    plotOptions: {
        pie: {
            borderColor: "#0c0c0c",
            borderWidth: 6,
            allowPointSelect: true,
            color: "#fff",
            cursor: 'pointer',
            dataLabels: {
                enabled: false,
            },
            showInLegend: true
        }
    },
    series: series
  };
  return (
    <div>
      {chartIsLoaded &&
        <HighchartsReact
          highcharts={Highcharts}
          options={options}
          ref={chartComponentRef}
          oneToOne={true}
        />
      }
    </div>
  );
};

chartData通过以下异步逻辑生成:

let data = sheetData[0].data;
let invesment = await groupData(data, "Investment Type");

当前问题:饼图和柱状图出现多次渲染的情况,但折线图无此问题。数据通过reduce函数结合await异步处理生成,尝试过用Promise处理,仍存在重复渲染现象。


修复方案

1. 移除不必要的渲染控制状态

chartIsLoaded状态仅在组件挂载后触发一次渲染,属于冗余逻辑,直接移除即可——HighchartsReact组件本身支持异步数据加载后的自动更新,无需额外控制渲染时机。

2. 缓存配置对象,避免引用变化触发重渲染

组件每次渲染时,series和options都会生成新的对象引用,导致HighchartsReact判定props变化并触发重渲染。使用useMemo缓存这两个对象,仅在依赖项变化时重新生成:

export const PieChart = (props: any) => {
  const chartComponentRef = useRef<HighchartsReact.RefObject>(null);
  
  // 缓存series,仅在name或chartData变化时更新
  const series = useMemo(() => [{
    innerSize: '80%',
    name: props.name,
    colorByPoint: true,
    data: props.chartData
  }], [props.name, props.chartData]);
  
  // 缓存options,仅在series变化时更新
  const options = useMemo((): Highcharts.Options => ({
    chart: {
        backgroundColor: "#0c0c0c",
        borderColor: "#0c0c0c",
        plotBorderWidth: 0,
        plotShadow: false,
        type: 'pie',
        height: "70%",
    },
    title: {
        style : { display : 'none' }
    },
    tooltip: {
      pointFormat: '<b>{point.percentage:.1f}%</b>',
      backgroundColor: "#1B1B1B",
      borderColor: "transparent",
      valueDecimals: 2,
      borderRadius: 0,
      style: { color: "#fff", fontSize: "15px" }
    },
    accessibility: { point: { valueSuffix: '%' } },
    legend: {
        itemStyle: {color: "#fff", fontWeight: "400", fontFamily: "teragon-sans"}
    },
    plotOptions: {
        pie: {
            borderColor: "#0c0c0c",
            borderWidth: 6,
            allowPointSelect: true,
            color: "#fff",
            cursor: 'pointer',
            dataLabels: { enabled: false },
            showInLegend: true
        }
    },
    series: series
  }), [series]);

  return (
    <div>
      <HighchartsReact
        highcharts={Highcharts}
        options={options}
        ref={chartComponentRef}
      />
    </div>
  );
};

3. 确保异步数据仅处理一次

在父组件中处理异步数据时,使用useEffect结合空依赖数组,避免重复执行数据处理逻辑导致子组件反复接收新数据:

// 父组件示例
const ParentComponent = () => {
  const [investmentData, setInvestmentData] = useState([]);
  
  useEffect(() => {
    const processData = async () => {
      const data = sheetData[0].data;
      const investment = await groupData(data, "Investment Type");
      setInvestmentData(investment);
    };
    processData();
  }, []); // 空依赖确保仅执行一次

  return <PieChart name="Investment" chartData={investmentData} />;
};

4. 调整HighchartsReact的oneToOne属性

oneToOne={true}会强制每次props变化时重建整个图表,而非更新现有图表。如果数据变化不需要重建图表,移除该属性,改用默认的增量更新逻辑,减少不必要的重渲染。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 14:54:24