我的用例是允许用户从大约8000家公司的长列表中选择一个股票行情。安装组件时,我会获取所有公司的信息,所以我实际上并不需要react-select的异步功能。问题实际上是显示和滚动显示8000个项目(如this one等一些未解决的问题中所述)。
我的想法是,当用户无法对如此大的列表做任何有意义的事情时,为什么会显示8000个条目。相反,为什么不显示最多5个匹配项。随着用户输入的内容越来越多,匹配度不断提高。具体来说:
我在任何地方都没有看到此解决方案,因此想知道它是否有意义。还希望找出使用react-select实现它的最佳方法是什么。我尝试了以下两种方法-您能想到更好的方法吗?
方法1:使用异步React Select
尽管我不需要异步获取,但是我可以使用此功能来过滤选项。看来效果很好:
const filterCompanies = (value: string) => {
const inputValue = value.trim().toLowerCase();
const inputLength = inputValue.length;
let count = 0;
return inputLength === 0
? []
: companies.filter(company => {
const keep =
count < 5 &&
(company.ticker.toLowerCase().indexOf(inputValue) >= 0 ||
company.name.toLowerCase().indexOf(inputValue) >= 0);
if (keep) {
count += 1;
}
return keep;
});
};
const promiseOptions = (inputValue: string) =>
Promise.resolve(filterCompanies(inputValue));
return (
<AsyncSelect<Company>
loadOptions={promiseOptions}
value={selectedCompany}
getOptionLabel={option => `${option.ticker} - ${option.name}`}
getOptionValue={option => option.ticker}
isClearable={true}
isSearchable={true}
onChange={handleChange}
/>
);
方法2:使用filterOption
在这里,我正在使用filterOption
直接过滤列表。但是,它不能很好地工作-filterOption函数非常近视-一次仅获得一个候选选项,需要确定是否匹配。使用这种方法,我无法判断我是否已超出显示5个选项的限制。最终结果:在输入为空的情况下,我将显示所有8000个选项,随着用户开始键入,选项的数量减少了,但数量仍然很大-因此速度仍然很慢。我本以为filterOption
对于我的用例来说将是更直接的方法,但事实证明它不如异步方法好。我想念什么吗?
const filterOption = (candidate: Option, input: string) => {
const { ticker, name } = candidate.data;
const inputVal = input.toLowerCase();
return (
ticker.toLowerCase().indexOf(inputVal) >= 0 ||
name.toLowerCase().indexOf(inputVal) >= 0
);
};
return (
<ReactSelect
options={companies}
value={selectedCompany}
filterOption={filterOption}
getOptionLabel={option => `${option.ticker} - ${option.name}`}
getOptionValue={option => option.ticker}
isClearable={true}
isSearchable={true}
onChange={handleChange}
/>
);
答案 0 :(得分:2)
您可以尝试使用react-window替换菜单列表组件
ref:https://github.com/JedWatson/react-select/issues/3128#issuecomment-431397942