ReactJs+ChartJs实现COVID-19数据可视化失败求助
问题分析与解决方案
咱们一步步来排查你代码里的问题,帮你搞定Chart.js的渲染问题:
1. 异步数据的时序问题
你在useEffect里先调用异步的getData,紧接着就执行setChart——这时候接口请求还没完成,state还是初始的空对象,所以chart里的state.cases、state.deaths全是undefined。而且useEffect的依赖数组是空的,就算后续接口返回数据更新了state,setChart也不会重新执行,图表永远拿不到有效数据。
2. 接口数据结构不匹配
你调用的接口返回的timeline里,cases、deaths这些字段是以日期为键的对象(比如{"1/22/20": 0, "1/23/20": 0,...}),但你直接把整个对象传给Chart.js的data数组,折线图需要的是数值数组,这也会导致渲染失败。
修复后的完整代码
App组件修改
import React, { useState, useEffect } from "react"; import axios from "axios"; import Chart from "./Chart"; const App = () => { const [timelineData, setTimelineData] = useState({}); const [loading, setLoading] = useState(true); const [chartData, setChartData] = useState({}); // 只负责发起数据请求 useEffect(() => { getData("italy"); }, []); // 监听timelineData变化,数据就绪后整理图表格式 useEffect(() => { if (Object.keys(timelineData).length > 0) { // 提取日期作为图表的x轴标签 const dates = Object.keys(timelineData.cases); // 提取对应的数据数组 const cases = Object.values(timelineData.cases); const deaths = Object.values(timelineData.deaths); const recovered = Object.values(timelineData.recovered); setChartData({ labels: dates, datasets: [ { label: "Cases", data: cases, borderColor: "rgb(255, 99, 132)", backgroundColor: "rgba(255, 99, 132, 0.2)" }, { label: "Deaths", data: deaths, borderColor: "rgb(54, 162, 235)", backgroundColor: "rgba(54, 162, 235, 0.2)" }, { label: "Recovered", data: recovered, borderColor: "rgb(75, 192, 192)", backgroundColor: "rgba(75, 192, 192, 0.2)" } ] }); setLoading(false); } }, [timelineData]); const getData = async country => { try { const res = await axios.get( `https://corona.lmao.ninja/v2/historical/${country}` ); setTimelineData(res.data.timeline); } catch (error) { console.log(error.response); setLoading(false); // 请求失败也要更新loading状态,避免页面卡死 } }; return ( <div> {loading ? "Loading data..." : <Chart chart={chartData} />} </div> ); }; export default App;
Chart组件优化(可选)
可以加个判断,防止数据未就绪时的报错:
import React from "react"; import { Line } from "react-chartjs-2"; const Chart = ({ chart }) => { // 如果图表数据未准备好,返回提示 if (!chart.labels || chart.datasets.length === 0) { return <div>Preparing chart...</div>; } return ( <div style={{ height: "400px", width: "800px" }}> <Line data={chart} options={{ maintainAspectRatio: false, title: { display: true, text: "Covid-19 Timeline", fontSize: 25 }, legend: { display: true, position: "top" } }} /> </div> ); }; export default Chart;
关键修复说明
- 拆分
useEffect:一个负责发起请求,另一个监听数据变化,确保数据返回后再生成图表配置,解决时序问题。 - 适配接口数据结构:把日期对象转成数组作为x轴标签,数值对象转成数组作为折线数据,符合Chart.js的要求。
- 增加错误处理:请求失败时更新loading状态,避免页面一直显示加载中。
- 添加配色:给每个数据集设置不同颜色,让可视化效果更清晰,和你期望的效果匹配。
这样修改后,你的折线图应该就能正常渲染出COVID-19的时间线数据了。
内容的提问来源于stack exchange,提问作者Hanzlah Tariq
相关产品推荐
相关产品推荐

