React Hooks中Echart按系列展示图表时数据被覆盖问题解决
问题根因
当前代码有两个核心逻辑错误,直接引发了数据覆盖、图表错位的问题:
- 状态更新逻辑错误:每次执行
setDataChart(DATA)时,是用新返回的单份图表数据完全替换dataChart的整个值,没有把新数据和历史已存数据做合并累加,所以新数据返回后,之前存好的旧数据会直接被清空。 - 数据源绑定逻辑错误:遍历渲染所有图表卡片时,每个
Echart组件共用同一个全局的dataChart['chart']数据源,没有按每个图表的唯一id做数据映射,导致所有位置的图表都在读取同一份全局数据,出现位置错位。 - 附带问题:循环内嵌套async逻辑时没有做状态隔离,还有局部变量和外层状态重名(内部定义的局部
data和外层全局data状态同名),极易引发逻辑混乱。
修复方案
1. 重构图表数据的状态结构
把原来存单个对象的dataChart状态,改成以每个图表唯一id为键的映射结构,用来存储所有已加载完成的图表数据,不同图表的数据互不干扰。
初始状态定义替换为:
const [dataChartMap, setDataChartMap] = useState<Record<string, any>>({})
2. 改造fetchChartDetail方法,实现数据累加不覆盖
在每个图表的请求返回后,只更新对应id下的数据源,绝不替换全量状态。把原来请求回调里的setDataChart(DATA)替换为函数式更新逻辑:
// 拿到上一次的状态做浅合并,仅更新对应id的图表数据 setDataChartMap(prevMap => ({ ...prevMap, [res.id]: { ...prevMap[res.id], chart: [{ ...configChart, data: response?.data?.data ?? [] }] } }))
必须使用函数式更新的写法,才能保证已经存好的chart1、chart2数据不会被新请求返回的chart3数据覆盖,真正实现按系列累加存储的效果。
同时删除代码里和外层状态重名的局部data变量,避免逻辑混淆。
3. 改造渲染逻辑,为每个图表绑定独立数据源
把原来所有Echart组件共用全局数据源的逻辑,改成每个遍历到的卡片,按自身的id从dataChartMap里读取对应的图表配置:
<Echart config={dataChartMap[item.id]?.chart ?? [configChart]} loading={item.spinning} colors={colors} dataZoom={true} />
改完后每个位置的图表只会渲染自己id对应的专属数据,不会出现位置错位、互相抢数据的问题。
4. 同步调整加载状态的更新逻辑
原来手动修改循环内对象引用的spinning标记逻辑,改为请求返回后对应更新data状态里的加载标记:
// 同步更新对应卡片的加载状态 setData(prevData => ({ ...prevData, data: prevData.data.map(item => item.id === res.id ? {...item, spinning: false} : item ) }))
调整完成后,每个图表的请求返回时只会把自身数据追加到映射表里,已经加载完成的旧数据不会被清空,每个图表位置永远渲染对应id的专属数据,完全匹配逐图加载、数据累加的预期效果。
内容的提问来源于stack exchange,提问作者user13780186
相关产品推荐
相关产品推荐

