React项目使用Chart.js渲染环形图报错:Canvas已被占用
解决方案
这个错误的核心原因是Chart.js实例未被正确销毁,导致Canvas元素被重复占用。以下是几种可行的解决方法:
1. 确保依赖版本兼容
react-chartjs-2与chart.js的版本需要匹配,比如v5.x的react-chartjs-2必须搭配v4.x的chart.js。检查你的package.json,确保依赖版本符合兼容要求(可根据实际情况调整为最新兼容版本):
{ "chart.js": "^4.4.0", "react-chartjs-2": "^5.2.0", "react": "^18.2.0", "react-dom": "^18.2.0" }
若版本不匹配,执行npm install重新安装对应版本的依赖。
2. 给图表组件添加唯一ID
给<Doughnut>组件指定唯一的id属性,避免Canvas复用冲突:
// 修改DoughnutChart.js的返回部分 return ( <div> <h1>Doughnut Chart</h1> <Doughnut data={data} id="unique-doughnut-chart" /> </div> );
3. 手动管理Chart实例的销毁(最可靠)
使用useRef保存Chart实例,并在组件卸载时调用destroy()方法销毁实例,彻底避免内存泄漏和Canvas冲突:
import React, { useEffect, useRef } from 'react'; import { Doughnut } from 'react-chartjs-2'; import { Chart } from 'chart.js'; const data = { labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'], datasets: [ { data: [12, 19, 3, 5, 2, 3], backgroundColor: ['#FF6384', '#36A2EB', '#FFCE56', '#4BC0C0', '#9966FF', '#FF9F40'], }, ], }; function DoughnutChart() { const chartRef = useRef(null); useEffect(() => { const chartInstance = chartRef.current?.chartInstance; // 组件卸载时销毁实例 return () => { if (chartInstance) { chartInstance.destroy(); } }; }, []); return ( <div> <h1>Doughnut Chart</h1> <Doughnut ref={chartRef} data={data} /> </div> ); } export default DoughnutChart;
4. 检查React StrictMode的影响
开发环境下,React.StrictMode会触发组件两次渲染,可能导致重复创建Chart实例。如果是临时测试,可以暂时移除index.js中的<React.StrictMode>包裹:
// index.js修改前 ReactDOM.render( <React.StrictMode> <App /> </React.StrictMode>, document.getElementById('root') ); // index.js修改后 ReactDOM.render( <App />, document.getElementById('root') );
注意:生产环境不会存在这个问题,上线前可以重新添加StrictMode。
内容的提问来源于stack exchange,提问作者Vidushika Dasanayka
相关产品推荐
相关产品推荐

