ReactJS中map遍历大量数据加载慢导致页面无响应如何解决?
问题根因
你遇到的页面无响应不是map函数执行慢,是一次性向DOM树插入14万+option节点,完全阻塞了浏览器主线程的渲染、交互逻辑,才会触发无响应提示。
实现加载状态+性能优化方案
首先要避免一次性渲染全量节点,同时增加加载状态标识,具体改造如下:
1. 状态调整
在state中新增loading状态标识加载进度,同时不要在constructor初始化时就加载全量城市数据到state,避免阻塞组件初始化。
2. 渲染逻辑优化(二选一即可)
- 分片渲染:将全量数据拆分为多段,每段渲染1000-2000条,利用浏览器空闲时间分段插入DOM,不会阻塞主线程,过程中显示加载提示
- 虚拟滚动:仅渲染当前可视区域内的节点(一般几十条),滚动时动态替换节点内容,是大数据量列表渲染的最优方案
3. 附加优化建议
14万+的下拉选项用户无法直接使用,建议增加输入搜索筛选功能,仅渲染匹配搜索关键词的少量节点,性能和体验都会大幅提升。
改造后参考代码
export default class addGy extends Component { constructor(props){ super(props); // 全量城市数据存在实例上,不进state避免不必要的渲染 this.allCities = City.getAllCities(); this.state = { countries: Country.getAllCountries(), states: State.getAllStates(), cities: [], // 初始为空,逐步加载 loading: true // 加载状态标识 } // 分片渲染配置:每次渲染2000条,可根据实际情况调整大小 this.chunkSize = 2000; this.renderIndex = 0; } componentDidMount() { navigator.geolocation.getCurrentPosition(function(position) { console.log(position) console.log("Latitude is :", position.coords.latitude); console.log("Longitude is :", position.coords.longitude); }); console.log(this.allCities) // 启动分片渲染 this.chunkRender(); } // 分片渲染逻辑 chunkRender = () => { const nextIndex = Math.min(this.renderIndex + this.chunkSize, this.allCities.length); // 取当前批次的城市数据 const chunkCities = this.allCities.slice(this.renderIndex, nextIndex); this.setState(prev => ({ cities: [...prev.cities, ...chunkCities] }), () => { this.renderIndex = nextIndex; if (nextIndex < this.allCities.length) { // 还有未渲染数据,下一帧继续渲染 requestAnimationFrame(this.chunkRender); } else { // 全部渲染完成,关闭加载状态 this.setState({ loading: false }) } }) } render() { return ( <Form> <Row className="mb-3"> <Form.Group as={Col} controlId="formGridCity"> <Form.Label>City {this.state.loading && '(加载中...)'}</Form.Label> <Form.Control as="select" multiple> { this.state.cities.map(ele=>{ return ( <option value={`${ele.name}`} className="d-inline mx-2 col-sm-5" onClick={({target}) => target.classList.toggle('bg-primary')} key={ele.name} // 必须加唯一key,避免React重复渲染损耗性能 > {ele.name} </option> ) }) } </Form.Control> </Form.Group> </Row> <Button variant="primary" type="submit" disabled={this.state.loading}> {this.state.loading ? '城市数据加载中' : 'Submit'} </Button> </Form> ); } }
内容的提问来源于stack exchange,提问作者streak
相关产品推荐
相关产品推荐

