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

React动态新增Chart.js图表报Canvas已占用错误修复

报错原因

这个报错和你已经渲染好的存量图表完全无关,不需要销毁任何已正常展示的图表就能修复。
核心触发原因是你动态循环渲染新增Chart组件时,没有给列表项加唯一key属性,React做虚拟DOM对比时会错误复用之前已经绑定过Chart实例的canvas节点,Chart.js检测到同一个canvas DOM已经被初始化过,就会抛出canvas被占用的错误。
另外你代码里JSX部分的// chart test code写法不对,JSX里不会把这种写法识别为注释,会直接把文本渲染到页面上。

修复方法

只需要做两处调整:

  • 给动态循环生成的每一个图表项绑定全局唯一的key,不要用数组下标当key,避免React错误复用canvas节点
  • 修正JSX的注释写法,避免无关文本渲染

修复后代码

import { Chart } from 'react-chartjs-2';
import { useState } from 'react';
// 提前注册用到的Chart.js组件,避免报元素未注册错误
import {
  Chart as ChartJS,
  LineElement,
  BarElement,
  PointElement,
  LinearScale,
  CategoryScale,
  Title,
  Tooltip,
  Legend,
} from 'chart.js';

ChartJS.register(
  LineElement,
  BarElement,
  PointElement,
  LinearScale,
  CategoryScale,
  Title,
  Tooltip,
  Legend
);

const Main = () => {
  // 存储新增图表配置,每个配置带唯一id作为渲染key
  const [count, setCount] = useState([]);

  const addWidget = () => {
    const newChart = {
      id: Date.now(), // 简单场景用时间戳做唯一id即可,复杂场景可替换为uuid
      config: {
        labels: ['1', '2', '3', '4', '5', '6', '7' , '8', '9','10'],
        datasets: [
          {
            type: 'line',
            label: 'Dataset 1',
            borderColor: 'rgb(54, 162, 235)',
            borderWidth: 2,
            data: [30, 9, 24, 50,-20,20, 17, 45, 49],
          }
        ],
      }
    }
    setCount([...count, newChart]);
  }

  // 替换成你自己项目里已有的配置
  const Line_data1 = {};
  const Bar_data = {};
  const options = {};
  const Bar_mutilLabel_options = {};

  return (
    <div>
      {/* chart test code */}
      <Chart data={Line_data1} options={options} style={{ position: "relative"}}/>
      <Chart data={Bar_data} options={Bar_mutilLabel_options} style={{ position: "relative"}}/>
      {count.map(el => (
        <div key={el.id}>
          <Chart style={{width:'10%'}} options={options} data={el.config}/>
        </div>
      ))}
      <button onClick={addWidget}>
        Click me
      </button>
    </div>
  )
}
注意事项
  • 不要用数组下标作为列表渲染的key:后续如果做图表删除、插入排序操作,下标变动还是会导致节点错误复用,用每个图表项独立的唯一id当key是最稳妥的方案。
  • 只有当你要替换同一个canvas位置的图表、或者卸载图表组件时,才需要手动调用chartInstance.destroy()销毁实例,你现在是新增独立图表的场景,完全不需要销毁已有的图表实例。
  • 如果你是手动封装Chart组件而非使用react-chartjs-2,记得在useEffect的清理函数里销毁当前组件对应的图表实例,避免组件卸载后内存残留,但这个逻辑和你现在的报错无关。

内容的提问来源于stack exchange,提问作者gavi Su

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.01 03:09:44