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

React中Chart.js图表悬停波动及图表销毁问题解决咨询

React中Chart.js的问题解决方案:悬停数据波动与图表销毁

一、解决鼠标悬停数据波动且保留Tooltip

你之前通过设置event:[]或hover: false抑制波动,但代价是丢失Tooltip功能。问题根源是禁用了全部hover交互,正确做法是保留必要交互配置,同时避免不必要重绘:

  • 移除hover: false和空的onHover函数
  • 合理配置hover模式,确保Tooltip正常工作的同时避免异常重绘
  • 把y轴的ticks.callback函数提取到组件外部,避免每次渲染创建新函数触发不必要重绘

二、解决切换数据时旧图表无法销毁的问题

当前代码中myChart是useEffect内部变量,外部无法访问,且useEffect依赖为空数组,数据变化时不会重新执行,导致旧图表残留。解决方案:

  • 使用useRef存储Chart实例,方便后续访问和销毁
  • 在useEffect的清理函数中销毁旧图表,防止内存泄漏
  • 将productData和truncatedNames加入useEffect依赖数组,确保数据变化时重新渲染图表

修改后的完整代码

import { useEffect, useRef } from 'react';
import Chart from "chart.js";

// 提取y轴回调函数到组件外部,避免每次渲染创建新函数
const yAxisLabelCallback = (value) => {
  // 这里写入你的数值格式化逻辑
  return value;
};

const emptyFunction = () => {};

const Component1 = ({ productData, truncatedNames }) => {
  // 用useRef存储Chart实例
  const chartRef = useRef(null);
  // 改用useRef绑定canvas,替代全局DOM查找
  const canvasRef = useRef(null);

  useEffect(() => {
    // 先销毁已有图表实例,避免叠加
    if (chartRef.current) {
      chartRef.current.destroy();
    }

    const ctx = canvasRef.current.getContext("2d");

    const data = {
      labels: truncatedNames,
      datasets: [
        {
          label: "Products",
          data: productData,
          backgroundColor: "#FA7070",
        },
      ],
    };

    const options = {
      responsive: true,
      scales: {
        yAxes: [
          {
            display: true,
            ticks: {
              suggestedMin: 0,
              beginAtZero: true,
              callback: productData ? yAxisLabelCallback : emptyFunction,
            },
          },
        ],
      },
      // 保留hover交互与Tooltip,配置合理的交互模式
      hover: {
        mode: 'index',
        intersect: false
      },
      tooltips: {
        enabled: true,
        mode: 'index',
        intersect: false
      }
    };

    // 创建新图表并存储到ref
    chartRef.current = new Chart(ctx, {
      type: "bar",
      data: data,
      options: options,
    });

    // 清理函数:组件卸载或数据变化时销毁图表
    return () => {
      if (chartRef.current) {
        chartRef.current.destroy();
      }
    };
  }, [productData, truncatedNames]); // 数据变化时触发重新渲染

  return (
    <Box>
      <canvas ref={canvasRef} width="70%" height="40%"></canvas>
    </Box>
  );
};

export default Component1;

关键说明

  1. 悬停波动修复:通过保留正常的hover和Tooltip配置,避免禁用全部交互;同时将回调函数提取到外部,防止因函数引用变化导致的不必要重绘。
  2. 图表销毁与更新:
    • useRef存储Chart实例,确保在清理函数和后续渲染中能访问到
    • 每次数据变化时先销毁旧图表再创建新图表,避免多个图表叠加
    • 使用canvasRef替代getElementById,符合React组件化规范,避免全局DOM查找的潜在问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 00:28:23