如何在react-select

时间:2019-04-26 17:53:23

标签: react-select

我的用例是允许用户从大约8000家公司的长列表中选择一个股票行情。安装组件时,我会获取所有公司的信息,所以我实际上并不需要react-select的异步功能。问题实际上是显示和滚动显示8000个项目(如this one等一些未解决的问题中所述)。

我的想法是,当用户无法对如此大的列表做任何有意义的事情时,为什么会显示8000个条目。相反,为什么不显示最多5个匹配项。随着用户输入的内容越来越多,匹配度不断提高。具体来说:

  • 当输入为空白时,不显示任何选项
  • 当输入为单个字符时,仍然会有数百个匹配项,但仅显示前5个
  • 随着用户不断输入内容,匹配项的数量将减少,但仍限于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}
    />

);

1 个答案:

答案 0 :(得分:2)

您可以尝试使用react-window替换菜单列表组件

ref:https://github.com/JedWatson/react-select/issues/3128#issuecomment-431397942