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

使用Highcharts在React项目构建仪表盘时遇layout.js模块错误求助

解决Highcharts Dashboards在React中的构建错误

错误原因分析

该错误通常由以下情况引发:

  • 模块导入/注册方式不符合Highcharts Dashboards规范
  • 重复初始化Dashboard实例,未清理旧实例导致DOM冲突
  • highcharts与@highcharts/dashboards版本不兼容

分步修复方案

1. 修正模块导入与注册逻辑

Highcharts Dashboards核心包已包含布局功能,无需单独导入LayoutModule,同时插件注册只需执行一次,移至组件外部:

import React, { useEffect, useState, useMemo } from 'react';
import Highcharts from 'highcharts';
import Dashboards from '@highcharts/dashboards';
import DataGrid from '@highcharts/dashboards/datagrid';
import axios from 'axios';

// 注册插件(组件外部仅执行一次)
Dashboards.HighchartsPlugin.custom.connectHighcharts(Highcharts);
Dashboards.DataGridPlugin.custom.connectDataGrid(DataGrid);
Dashboards.PluginHandler.addPlugin(Dashboards.HighchartsPlugin);
Dashboards.PluginHandler.addPlugin(Dashboards.DataGridPlugin);

2. 清理旧Dashboard实例

组件重新渲染或卸载时,必须销毁旧实例,避免内存泄漏和DOM冲突:

useEffect(() => {
  // 先销毁已存在的board实例
  if (Dashboards.boardInstances['container']) {
    Dashboards.boardInstances['container'].destroy();
  }

  // 数据未加载时不初始化
  if (data.length === 0) return;

  const board = Dashboards.board('container', {
    // 原配置内容保持不变
  });

  // 组件卸载时销毁实例
  return () => board.destroy();
}, [data, totalRegistrations, totalStates, chartData]);

3. 优化数据计算逻辑

使用useMemo缓存计算结果,避免因数组引用频繁变化导致useEffect重复触发:

const totalRegistrations = useMemo(() => 
  data.reduce((acc, curr) => acc + curr.count, 0), 
  [data]
);

const totalStates = useMemo(() => data.length, [data]);

// 复用同一数据数组,减少冗余计算
const chartData = useMemo(() => 
  data.map(item => ({ name: item.statename, y: item.count })), 
  [data]
);

4. 确保依赖版本兼容

卸载现有包后,安装同主版本的匹配依赖:

npm uninstall highcharts @highcharts/dashboards
npm install highcharts@latest @highcharts/dashboards@latest

完整修复后的组件代码

import React, { useEffect, useState, useMemo } from 'react';
import Highcharts from 'highcharts';
import Dashboards from '@highcharts/dashboards';
import DataGrid from '@highcharts/dashboards/datagrid';
import axios from 'axios';

// 注册插件(组件外部仅执行一次)
Dashboards.HighchartsPlugin.custom.connectHighcharts(Highcharts);
Dashboards.DataGridPlugin.custom.connectDataGrid(DataGrid);
Dashboards.PluginHandler.addPlugin(Dashboards.HighchartsPlugin);
Dashboards.PluginHandler.addPlugin(Dashboards.DataGridPlugin);

const Dashboard = () => {
  const [data, setData] = useState([]);

  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await axios.get('https://stage-backend-2024.epravaha.com/api/farmer/count/statewise');
        setData(response.data);
      } catch (error) {
        console.error('Error fetching data:', error);
      }
    };
    fetchData();
  }, []);

  // 缓存计算结果
  const totalRegistrations = useMemo(() => 
    data.reduce((acc, curr) => acc + curr.count, 0), 
    [data]
  );

  const totalStates = useMemo(() => data.length, [data]);

  const chartData = useMemo(() => 
    data.map(item => ({ name: item.statename, y: item.count })), 
    [data]
  );

  useEffect(() => {
    // 清理旧实例
    if (Dashboards.boardInstances['container']) {
      Dashboards.boardInstances['container'].destroy();
    }

    if (data.length === 0) return;

    const board = Dashboards.board('container', {
      editMode: {
        enabled: true,
        contextMenu: {
          enabled: true,
          items: ['editMode'],
        },
      },
      gui: {
        layouts: [{
          id: 'layout-1',
          rows: [{
            cells: [{
              id: 'row-1',
              layout: {
                cells: [{
                  id: 'kpi-chart1',
                  componentType: 'KPI',
                  data: {
                    value: totalRegistrations,
                    label: 'Total Farmer Registrations'
                  }
                }, {
                  id: 'kpi-chart2',
                  componentType: 'KPI',
                  data: {
                    value: totalStates,
                    label: 'Total States'
                  }
                }]
              }
            }]
          }, {
            cells: [{
              id: 'row-2',
              layout: {
                cells: [{
                  id: 'bar-chart',
                  componentType: 'Highcharts',
                  chartType: 'bar',
                  options: {
                    chart: { type: 'bar' },
                    title: { text: 'Bar Chart' },
                    xAxis: { categories: chartData.map(item => item.name) },
                    series: [{
                      name: 'Number of Farmer Registrations',
                      data: chartData.map(item => item.y)
                    }]
                  }
                }, {
                  id: 'pie-chart',
                  componentType: 'Highcharts',
                  chartType: 'pie',
                  options: {
                    chart: { type: 'pie' },
                    title: { text: 'Pie Chart' },
                    series: [{
                      name: 'Number of Farmer Registrations',
                      data: chartData
                    }]
                  }
                }]
              }
            }]
          }, {
            cells: [{
              id: 'row-3',
              layout: {
                cells: [{
                  id: 'donut-chart',
                  componentType: 'Highcharts',
                  chartType: 'pie',
                  options: {
                    chart: { type: 'pie' },
                    title: { text: 'Donut Chart' },
                    plotOptions: {
                      pie: { innerSize: '50%', depth: 45 }
                    },
                    series: [{
                      name: 'Number of Farmer Registrations',
                      data: chartData
                    }]
                  }
                }, {
                  id: 'column-chart',
                  componentType: 'Highcharts',
                  chartType: 'column',
                  options: {
                    chart: { type: 'column' },
                    title: { text: 'Column Chart' },
                    xAxis: { categories: chartData.map(item => item.name) },
                    series: [{
                      name: 'Number of Farmer Registrations',
                      data: chartData.map(item => item.y)
                    }]
                  }
                }]
              }
            }]
          }]
        }]
      }
    });

    return () => board.destroy();
  }, [data, totalRegistrations, totalStates, chartData]);

  return <div id="container" style={{ width: '100%', height: '100vh' }}></div>;
};

export default Dashboard;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 03:19:54