我正在尝试解决React应用程序中发生的问题。在其中一个视图(组件)中,我有一个可处理大数据的管理工具。基本上,当视图加载时,我会触发componentDidMount
来触发ajax提取,该提取将下载由大约50.000条记录组成的数组。每个数组行都是一个具有8-10个键值对的对象。
import React, { Component } from "react";
import { List } from "react-virtualized";
import Select from "react-select";
class Market extends Component {
state = {
sports: [], // ~ 100 items
settlements: [], // ~ 50k items
selected: {
sport: null,
settlement: null
}
};
componentDidMount() {
this.getSports();
this.getSettlements();
}
getSports = async () => {
let response = await Ajax.get(API.sports);
if (response === undefined) {
return false;
}
this.setState({ sports: response.data });
};
getSettlements = async () => {
let response = await Ajax.get(API.settlements);
if (response === undefined) {
return false;
}
this.setState({ settlements: response.data });
};
save = (key, option) => {
let selected = { ...this.state.selected };
selected[key] = option;
this.setState({ selected });
};
virtualizedMenu = props => {
const rows = props.children;
const rowRenderer = ({ key, index, isScrolling, isVisible, style }) => (
<div key={key} style={style}>
{rows[index]}
</div>
);
return (
<List
style={{ width: "100%" }}
width={300}
height={300}
rowHeight={30}
rowCount={rows.length || 1}
rowRenderer={rowRenderer}
/>
);
};
render() {
const MenuList = this.virtualizedMenu;
return (
<div>
<Select
value={this.state.selected.sport}
options={this.state.sports.map(option => {
return {
value: option.id,
label: option.name
};
})}
onChange={option => this.save("sport", option)}
/>
<Select
components={{ MenuList }}
value={this.state.selected.settlement}
options={this.state.settlements.map(option => {
return {
value: option.id,
label: option.name
};
})}
onChange={option => this.save("settlement", option)}
/>
</div>
);
}
}
我遇到的问题是,在下载大数据并将其保存为查看状态之后,即使我要使用具有〜100条记录的select来更新值,也要花几秒钟的时间。例如,假设smallData
是100个项目的数组,而{ id: n, name: 'xyz' }
和selectedFromSmallData
只是数据数组中的单个项目,使用html select进行选择。
在大数据加载之前进行选择需要花费ms
,但是在数据加载并保存到状态后,突然需要2-4秒。
可能会帮助解决该问题的方法(不幸的是,我无法分页该数据,而我无法访问其任何内容)。
答案 0 :(得分:1)
.map()
在每个渲染器上创建一个新数组。为避免这种情况,您有以下三种选择:
state.sports
和state.settlements
已为Select
准备的state.sports
或state.settlements
时也会更改state.sportsOptions
或state.settlementsOptions
componentDidUpdate
更新state.*Options
:第三个选项可能更易于实现。但这会触发其他重新渲染:
componentDidUpdate(prevProps, prevState) {
if (prevState.sports !== this.state.sports) {
this.setState(oldState => ({sportsOptions: oldState.sports.map(...)}));
}
...
}
您的onChange
处理程序将在每次渲染时重新创建,并可能触发Select
的不必要的重新渲染。创建两个单独的方法来避免这种情况:
saveSports = option => this.save("sport", option)
...
render() {
...
<Select onChange={this.saveSports}/>
...
}
您对components={{ MenuList }}
有类似的问题。将其移至状态或构造函数,这样{MenuList}
对象仅创建一次。您应该以如下形式结束:
<Select
components={this.MenuList}
value={this.state.selected.settlement}
options={this.state.settlementsOptions}
onChange={this.saveSettlements}
/>
如果这样做没有帮助,请考虑使用默认的select
并使用PureComponent
来呈现其选项。或尝试使用custom PureComponents
渲染Select
的一部分。
答案 1 :(得分:0)
数组的大小应该不成问题,因为只有引用存储在状态对象中,而react不会对状态做任何深度相等。 也许您的render或componentDidUpdate在这个大数组上进行迭代,这会导致问题。 如果这样做没有帮助,请尝试配置您的应用。