React JS下拉切换时数组未清空导致旧数据累积问题
问题根因
你的代码出现旧数据残留是几个明确的逻辑错误导致的:
- 开头写的数组清空逻辑完全无效:你刚声明
var newArray = []时这个数组本身就是空的,对空数组执行forEach遍历加splice删除没有任何实际作用。 - 清空逻辑执行完后你写了
newArray = this.state.data.slice(),直接把state里存储的上一次加载的旧数据完整拷贝到了新数组里,后续接口返回数据你是往这个已经带了旧数据的数组里push,自然会把新旧数据拼接到一起,长度持续增长。 - 存在请求竞态隐患:如果用户快速切换下拉选项,多个接口请求的返回顺序不可控,可能出现后选的选项先返回、先选的选项后返回的情况,最终页面会展示错误的旧数据。
- 额外的渲染逻辑错误:你在接口请求的回调里手动调用
fetchChart(),但React组件的state更新会自动触发重渲染,手动调用渲染方法会导致状态和视图不同步。
修复步骤
- 删除完全无效的空数组遍历清空代码,接口返回数据后不要基于旧state的data做拼接,直接用接口返回的全新数据构造数组。
- 增加请求ID标记,处理快速切换下拉的竞态问题,只有最后一次触发的请求返回结果才允许更新state。
- 删掉接口回调里手动调用
fetchChart()的代码,state更新后render函数会自动重新执行,渲染最新的图表数据。 - 去掉render里对事件处理函数的
bind调用,你已经用类箭头函数的写法定义了onDropdownChange,本身已经绑定了this,每次render都bind会生成新的函数实例,触发不必要的组件重渲染。
修正后完整代码
import React from 'react'; import axios from 'axios'; // 其他组件导入省略:CustomLineChart、CustomDropdownList class Dashboard extends React.Component { // 用于标记最新请求ID,处理竞态问题 latestRequestId = 0; state = { data: [], items: [] } onDropdownChange = (selectedVal) => { // 每次触发下拉切换,自增请求ID,记录当前是最新一次请求 const currentRequestId = ++this.latestRequestId; const url = `https://abcdefgh...../${selectedVal}/readings?today`; axios.get(url).then(res => { // 如果当前请求不是最新触发的,直接丢弃结果,避免旧数据覆盖新数据 if (currentRequestId !== this.latestRequestId) return; // 直接从接口返回数据构造新数组,完全不引用旧的state数据,从根源避免旧数据残留 const responseItems = res.data.items; const newArray = responseItems.map(item => ({ time: item.dateTime, TM: item.value })); // 排序后更新state,state更新会自动触发组件重渲染 const sortedArray = newArray.sort((a, b) => new Date(a.time).getTime() - new Date(b.time).getTime()); this.setState({ data: sortedArray, items: responseItems }); }); } render() { const { items, data } = this.state; const itemList = items.map(item => { return <tr key={`${item.dateTime}${item.value}`}> <td style={{whiteSpace: 'nowrap'}}>{item.dateTime}</td> <td>{item.measure}</td> <td>{item.value}</td> </tr> }); return ( <div> <CustomLineChart data={data} /> <CustomDropdownList changeLink={this.onDropdownChange} /> {/* 如需渲染表格,放开下方注释即可 */} {/* <table><tbody>{itemList}</tbody></table> */} </div> ); } } export default Dashboard;
补充说明:原来代码里
fetchChart方法没有实际存在的必要,直接在render里渲染图表组件即可,逻辑更清晰也更符合React的单向数据流规则。
内容的提问来源于stack exchange,提问作者chk.buddi
相关产品推荐
相关产品推荐

