React+Chart.js展示接口数据报错:无法读取datasets属性
解决React结合Chart.js时接口数据无法渲染图表的问题
问题根源
- 代码执行顺序错误:你在
mondayData定义之前就尝试修改它的datasets.data,此时mondayData还未初始化,必然触发“Cannot read properties of undefined”错误。 - 变量作用域失效:在
backendData.map内部定义的total仅在回调函数内有效,外部无法访问该值。 - 未使用React状态管理:
mondayData是普通变量,React无法感知其变化,接口返回数据后组件不会重新渲染,图表也无法更新。 - 数据结构不匹配:
backendData初始值是数组,但后端返回的是单个对象,用map遍历完全多余。
修正后的代码
import { useState, useEffect } from 'react'; import axios from 'axios'; import Chart from 'chart.js/auto'; function ParkingChart() { // 将图表数据存入React状态,让框架能追踪变化 const [chartData, setChartData] = useState({ labels: ["7 AM", "8 AM", "9 AM", "10 AM", "11 AM", "12 PM", "1 PM", "2 PM", "3 PM"], datasets: [{ data: [2, 1, 1, 6, 4, 7, 8, 14, 13], label: "Empty parking spaces", backgroundColor: "rgb(39, 63, 150, 0.5)", }] }); // 发起接口请求,获取数据后更新图表状态 useEffect(() => { axios.get('http://localhost:3001/get') .then((response) => { const { total } = response.data; // 函数式更新状态,避免直接修改原数据 setChartData(prevData => ({ ...prevData, datasets: prevData.datasets.map(dataset => ({ ...dataset, data: [total, ...dataset.data.slice(1)] // 将total替换为数组第一个元素 })) })); }) .catch(err => console.error('获取数据失败:', err)); }, []); // 监听图表数据变化,更新图表实例 useEffect(() => { const mondayCtx = document.getElementById('mondayChart').getContext('2d'); // 销毁已存在的图表实例,避免重复创建 let existingChart = Chart.getChart("mondayChart"); if (existingChart) { existingChart.destroy(); } // 创建新的图表 new Chart(mondayCtx, { type: 'line', data: chartData, options: {} }); // 组件卸载时清理图表,防止内存泄漏 return () => { const chart = Chart.getChart("mondayChart"); if (chart) chart.destroy(); }; }, [chartData]); // 依赖chartData,数据变化时重新渲染图表 return <canvas id="mondayChart"></canvas>; } export default ParkingChart;
核心改动说明
- 用useState管理图表数据:将图表数据转为React状态,数据更新时组件自动重新渲染,触发图表更新。
- 正确更新状态:通过函数式更新复制原数据并替换目标值,遵循React不可变状态规则。
- 监听数据变化渲染图表:第二个
useEffect依赖chartData,数据变化时重新创建图表,保证视图与数据同步。 - 清理图表实例:添加组件卸载时的清理函数,销毁图表实例避免内存泄漏。
- 简化数据访问:后端返回单个对象,直接解构
total即可,无需多余的数组遍历。
内容的提问来源于stack exchange,提问作者hedgers
相关产品推荐
相关产品推荐

