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
相关产品推荐
相关产品推荐

