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更新逻辑被注释:原本用于存储性别计数的
genderCountstate更新代码被注释,没有将获取到的计数同步到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;
关键修改点
- 用state存储计数:将
maleCount和femaleCount替换为genderCounts状态变量,确保数据更新时触发组件重渲染。 - 移除无效的普通变量:将计数逻辑移到useEffect内部,避免组件渲染时重复初始化普通变量。
- 确保图表数据依赖state:图表的
data对象直接使用genderCounts状态的值,保证每次重渲染都能拿到最新数据。 - 新增固定容器尺寸:给Pie组件包裹一个固定宽高的容器,确保图表有足够的渲染空间。
内容的提问来源于stack exchange,提问作者hussain ashraf
相关产品推荐
相关产品推荐

