React函数组件使用Chart.js无法切换数据报properties undefined错误如何解决
React中Chart.js实例跨作用域访问、更新的解决方案
问题根因
报错核心原因是对React useState的使用错误,附带存在useEffect、逻辑判断的写法问题:
- 直接给
setPositiveChart赋值,覆盖了useState返回的状态更新函数,Chart实例从未被存入positiveChart状态,导致状态始终是初始值undefined,访问属性时自然报错 - 直接给useEffect传入async回调,返回的Promise会覆盖清理函数,导致Chart实例销毁逻辑不生效
- toggle函数的两个并列if判断存在逻辑冲突,执行hide后第二个判断条件会立刻成立,导致刚隐藏的数据集又被显示
修正方案
按照以下步骤修改即可实现全组件内访问Chart实例、正常触发更新:
- 在makeChart函数中先创建Chart实例,再调用state更新函数将实例存入状态
- 修正useEffect的异步写法和销毁逻辑
- 优化toggle函数的判断逻辑
修正后的完整代码如下:
import React, { useContext, useEffect, useState } from "react"; import "./questions_trends.css"; import axios from 'axios'; import ReactTooltip from 'react-tooltip'; import { Chart } from "chart.js"; // 注意如果你的UserContext没有在当前文件导入,需要补充对应导入逻辑 const UserContext = React.createContext(); function Trends(){ const user_context = useContext(UserContext) const [positiveChart, setPositiveChart] = useState(undefined); function makeChart(data){ // 先创建Chart实例 const chartInstance = new Chart('positiveChart', { type: 'bar', data: { labels: data.positive, datasets: [ { label: 'Team Positive', data: data.team_positive, backgroundColor: data.color }, { label: 'You Positive', data: data.positive, backgroundColor: data.color }] }, options: {} }); // 调用state更新函数将实例存入状态 setPositiveChart(chartInstance); } function toggle(value) { // 先判断实例是否存在,避免报错 if(!positiveChart) return; // 改用if else避免逻辑冲突 if(positiveChart.isDatasetVisible(value)){ positiveChart.hide(value) } else { positiveChart.show(value) } } useEffect(() => { // 异步逻辑写在useEffect内部的独立函数中,不要直接给useEffect回调加async const fetchData = async () => { let result = await axios.get("/api/monthly_tones") makeChart(result.data) } fetchData(); // 清理逻辑写在当前useEffect的返回中,不需要单独写一个useEffect return () => { if(positiveChart) { positiveChart.destroy() } } }, []); return ( <div className="question_positivity_container"> <canvas id="positiveChart" width="auto" height="70vh"></canvas> <button onClick={() => toggle(0)}>See All Cratic</button> </div> ); }; export default Trends;
验证逻辑
修改完成后:
- Chart初始化完成后实例会被存入positiveChart状态,全组件范围内都可以正常访问
- 点击按钮可正常切换数据集的显隐
- 组件卸载时会自动销毁Chart实例,避免内存泄漏
内容的提问来源于stack exchange,提问作者Izzi
相关产品推荐
相关产品推荐

