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

React中react-chartjs-2的Pie Chart无法渲染问题求助

问题:React中react-chartjs-2饼图未渲染(API数据已获取)

我在React组件中使用react-chartjs-2结合Chart.js渲染饼图时遇到问题。饼图数据从API获取,预期数据就绪后渲染,但尽管数据已成功获取,饼图仍未显示在页面上。

代码片段

// Dashboard.js
import React, { useEffect, useState } from 'react';
import axios from 'axios';
import { useUser } from '../UserContext';
import { AppBar, Toolbar, Typography, Container, Box } from '@mui/material';
import { Chart as ChartJS, ArcElement, Tooltip, Legend } from "chart.js";
import { Pie } from 'react-chartjs-2';
ChartJS.register(ArcElement, Tooltip, Legend);
const Dashboard = () => {
  const { userData } = useUser();
  const [genderCount, setGenderCount] = useState([]);
  const [loading, setLoading] = useState(true);
  let maleCount = 0;
  let femaleCount = 0;

  useEffect(() => {
    axios
      .get('https://randomuser.me/api/?results=10')
      .then(response => {
        const users = response.data.results;
        console.log(users)
        // Iterate over the users to count genders
        users.forEach(user => {
          if (user.gender === 'male') {
            maleCount++;
          } else if (user.gender === 'female') {
            femaleCount++;
          }
        });

        // Update the state with gender count
        // setGenderCount([
        //   { gender: 'male', count: maleCount },
        //   { gender: 'female', count: femaleCount }
        // ]);
        setLoading(false);
        console.log('male',maleCount)
        console.log('female',femaleCount)

      })
      .catch(error => {
        console.error('Error fetching data:', error);
        setLoading(false);
      });
  }, []);

  // Extract data for the pie chart
 const data = {
    labels: ['Male', 'Female'],
    datasets: [
      {
        label: '# of Votes',
        data: [maleCount,femaleCount],
        backgroundColor: [
          'rgba(255, 99, 132, 0.2)',
          'rgba(54, 162, 235, 0.2)',
        ],
        borderColor: [
          'rgba(255, 99, 132, 1)',
          'rgba(54, 162, 235, 1)',

        ],
        borderWidth: 1,
      },
    ],
  };

  return (
    <Container>
      <AppBar position="fixed">
        <Toolbar>
          <Box sx={{ flexGrow: 1 }}>
            <Typography variant="h6" component="div">
              Your Logo
            </Typography>
          </Box>
          <Typography variant="h6" component="div">
            {userData && `Welcome, ${userData.username}!`}
          </Typography>
        </Toolbar>
      </AppBar>

      <Box sx={{ marginTop: '4rem', width: '80%', margin: 'auto' }}>
        <h2>Dashboard</h2>
        {  (
          <div>
            {/* Display other user information */}
            
            {/* Conditionally render pie chart when data is available */}
            {loading ? (
              <p>Loading...</p>
            ) : (
              <div>
                <h3>Gender Counts</h3>
                <Pie data={data}/>
              </div>
            )}
          </div>
        )}
      </Box>
    </Container>
  );
};

export default Dashboard;

问题细节

  • 已确认数据获取正常
  • 数据就绪时已将loading状态设为false
  • 使用react-chartjs-2的Pie组件
  • 已设置图表宽高

具体问题:即使确认数据获取完成且loading状态为false,饼图仍未显示。尝试调整图表宽高,问题未解决。


原因分析

  • 普通变量无法触发组件重渲染:maleCount和femaleCount是组件内的普通变量,不是React状态(useState)。在useEffect中更新这两个变量后,组件不会重新渲染,图表的data对象仍然使用初始值[0,0],导致饼图无内容可显示。
  • state更新逻辑被注释:原本用于存储性别计数的genderCount state更新代码被注释,没有将获取到的计数同步到React状态中,组件无法感知数据变化。

修复方案

将性别计数存入React状态,确保数据更新时触发组件重渲染,让图表获取到最新数据。

修改后的代码

// Dashboard.js
import React, { useEffect, useState } from 'react';
import axios from 'axios';
import { useUser } from '../UserContext';
import { AppBar, Toolbar, Typography, Container, Box } from '@mui/material';
import { Chart as ChartJS, ArcElement, Tooltip, Legend } from "chart.js";
import { Pie } from 'react-chartjs-2';
ChartJS.register(ArcElement, Tooltip, Legend);
const Dashboard = () => {
  const { userData } = useUser();
  // 用state存储性别计数,替代普通变量
  const [genderCounts, setGenderCounts] = useState({ male: 0, female: 0 });
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    axios
      .get('https://randomuser.me/api/?results=10')
      .then(response => {
        const users = response.data.results;
        let maleCount = 0;
        let femaleCount = 0;
        
        users.forEach(user => {
          if (user.gender === 'male') {
            maleCount++;
          } else if (user.gender === 'female') {
            femaleCount++;
          }
        });

        // 更新state,触发组件重渲染
        setGenderCounts({ male: maleCount, female: femaleCount });
        setLoading(false);
      })
      .catch(error => {
        console.error('Error fetching data:', error);
        setLoading(false);
      });
  }, []);

  // 基于state生成图表数据,确保每次重渲染都拿到最新值
 const data = {
    labels: ['Male', 'Female'],
    datasets: [
      {
        label: '# of Users',
        data: [genderCounts.male, genderCounts.female],
        backgroundColor: [
          'rgba(255, 99, 132, 0.2)',
          'rgba(54, 162, 235, 0.2)',
        ],
        borderColor: [
          'rgba(255, 99, 132, 1)',
          'rgba(54, 162, 235, 1)',
        ],
        borderWidth: 1,
      },
    ],
  };

  return (
    <Container>
      <AppBar position="fixed">
        <Toolbar>
          <Box sx={{ flexGrow: 1 }}>
            <Typography variant="h6" component="div">
              Your Logo
            </Typography>
          </Box>
          <Typography variant="h6" component="div">
            {userData && `Welcome, ${userData.username}!`}
          </Typography>
        </Toolbar>
      </AppBar>

      <Box sx={{ marginTop: '4rem', width: '80%', margin: 'auto' }}>
        <h2>Dashboard</h2>
        <div>
          {loading ? (
            <p>Loading...</p>
          ) : (
            <div>
              <h3>Gender Counts</h3>
              {/* 给Pie组件设置固定尺寸,避免渲染问题 */}
              <div style={{ width: '400px', height: '400px', margin: '0 auto' }}>
                <Pie data={data}/>
              </div>
            </div>
          )}
        </div>
      </Box>
    </Container>
  );
};

export default Dashboard;

关键修改点

  1. 用state存储计数:将maleCount和femaleCount替换为genderCounts状态变量,确保数据更新时触发组件重渲染。
  2. 移除无效的普通变量:将计数逻辑移到useEffect内部,避免组件渲染时重复初始化普通变量。
  3. 确保图表数据依赖state:图表的data对象直接使用genderCounts状态的值,保证每次重渲染都能拿到最新数据。
  4. 新增固定容器尺寸:给Pie组件包裹一个固定宽高的容器,确保图表有足够的渲染空间。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 08:25:23