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

React+Chart.js环形图组件问题:中心总和值不显示/渲染报错

React + Chart.js 环形图(带中心总和)问题解决

问题根源分析

  1. 无状态钩子时总和为0:大概率是你在组件初始化阶段就计算了总和,但传入的props数据是异步加载的,初始时数据集为空,总和被设为0后,数据更新时没有重新触发计算逻辑。
  2. 使用useState/useEffect后渲染报错:要么是useEffect的依赖项设置错误,导致无限重渲染;要么是没有处理数据集为空的边界情况,直接对undefined执行map操作。

解决方案代码

先确保安装了必要依赖:

npm install chart.js react-chartjs-2

完整环形图组件

import React from 'react';
import { Doughnut } from 'react-chartjs-2';
import { Chart as ChartJS, ArcElement, Tooltip, Legend } from 'chart.js';

// 注册Chart.js核心组件,避免渲染异常
ChartJS.register(ArcElement, Tooltip, Legend);

const DoughnutWithTotal = ({ dataSet, displayType }) => {
  // 边界处理:数据集为空时显示加载状态
  if (!dataSet || dataSet.length === 0) {
    return <div>加载中...</div>;
  }

  // 实时计算图表数据与总和,无需额外状态存储
  const getChartInfo = () => {
    let total = 0;
    const labels = [];
    const values = [];

    dataSet.forEach(item => {
      labels.push(item.account_type);
      const currentValue = displayType === 'balance' ? item.balance : item.count;
      values.push(currentValue);
      total += currentValue;
    });

    return {
      labels,
      datasets: [{
        data: values,
        backgroundColor: ['#FF6384', '#36A2EB', '#FFCE56', '#4BC0C0'],
        hoverBackgroundColor: ['#FF6384', '#36A2EB', '#FFCE56', '#4BC0C0']
      }],
      total
    };
  };

  const chartInfo = getChartInfo();

  return (
    <div style={{ position: 'relative', width: '300px', height: '300px' }}>
      <Doughnut
        data={chartInfo}
        options={{
          cutout: '70%', // 控制环形内圈大小,留出中心位置
          plugins: {
            legend: { position: 'bottom' }
          }
        }}
      />
      {/* 绝对定位实现中心总和展示 */}
      <div style={{
        position: 'absolute',
        top: '50%',
        left: '50%',
        transform: 'translate(-50%, -50%)',
        textAlign: 'center'
      }}>
        <div style={{ fontSize: '24px', fontWeight: 'bold' }}>{chartInfo.total}</div>
        <div style={{ fontSize: '14px', color: '#666' }}>
          {displayType === 'balance' ? '总余额' : '总数量'}
        </div>
      </div>
    </div>
  );
};

// 组件使用示例
const App = () => {
  // 模拟props传入的数据集
  const mockData = [
    { account_type: '储蓄账户', balance: 15000, count: 3 },
    { account_type: '投资账户', balance: 35000, count: 2 },
    { account_type: '信用卡账户', balance: 8000, count: 4 }
  ];

  return (
    <div style={{ display: 'flex', gap: '50px', padding: '20px' }}>
      <DoughnutWithTotal dataSet={mockData} displayType="balance" />
      <DoughnutWithTotal dataSet={mockData} displayType="count" />
    </div>
  );
};

export default App;

关键优化点

  • 实时计算替代状态存储:每次组件渲染时基于最新props计算数据与总和,避免状态不同步问题。
  • 边界情况处理:提前判断数据集是否为空,防止undefined.map错误。
  • 中心总和布局:通过绝对定位+transform实现居中,配合cutout参数控制环形内圈大小,确保总和显示在正确位置。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 04:10:32