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

切换图表类型后Chart.js实例ctx与canvas为null的问题解决

问题原因
  • 切换图表类型时,原图表组件(如<Doughnut>)会被React卸载,对应的Chart.js实例会被销毁,此时chartRef.current指向的是已销毁的实例,其ctx和canvas属性自然变为null。
  • 你在组件顶层直接将chart赋值为chartRef.current,这个值只会在组件首次渲染时获取一次。当切换回饼图时,新的Chart实例被创建,但chart变量仍然指向旧的销毁实例,导致点击函数调用失效。
解决方法

方法1:在点击函数中实时获取最新的Chart实例

不要在组件顶层提前赋值chart,而是在legendClickHandler里直接使用chartRef.current,确保每次点击都拿到当前活跃的Chart实例:

// 移除顶层的const chart = chartRef.current;
const legendClickHandler = (index) => {
  const chart = chartRef.current; // 实时获取最新实例
  if (!chart) return; // 避免实例未加载时出错
  const { type } = chart.config;
  if (type === 'pie' || type === 'doughnut') {
    chart.toggleDataVisibility(index);
    chart.update();
  }
};

方法2:使用useEffect监听图表类型变化(可选)

如果需要在其他逻辑中也访问最新实例,可以配合useEffect更新状态变量:

import { useRef, useState, useEffect } from 'react';

const Graph = (props) => {
  const [chartType, setChartType] = useState({
    id: 'c1',
    name: 'Pie Chart',
    value: 'pie',
  });
  const chartRef = useRef(null);
  const [currentChart, setCurrentChart] = useState(null);

  useEffect(() => {
    setCurrentChart(chartRef.current);
  }, [chartType]); // 图表类型切换后更新当前实例

  const legendClickHandler = (index) => {
    if (!currentChart) return;
    const { type } = currentChart.config;
    if (type === 'pie' || type === 'doughnut') {
      currentChart.toggleDataVisibility(index);
      currentChart.update();
    }
  };

  // 其余渲染代码保持不变
};

额外注意事项

  • 切换图表类型时,新的图表组件会自动挂载,chartRef会指向新创建的Chart实例,无需手动重置ref。
  • 点击函数中添加if (!chart)的判断,可以避免图表未完全加载时触发点击导致报错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 07:30:52