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

