具有非常大的选项列表的 React Select

Posted

技术标签:

【中文标题】具有非常大的选项列表的 React Select【英文标题】:React Select with very large options lists 【发布时间】:2018-08-13 14:42:59 【问题描述】:

我有一个选择组件,它需要处理其中大约 7,000 个选项。我遇到了两个问题。

1) 输入搜索参数时加载速度太慢。

2) 我需要过滤所有选项并禁用以前选择的选项(从我从数据库加载的值中)或刚刚在此页面加载时选择的选项。

对于第一个问题,我尝试利用https://github.com/bvaughn/react-select-fast-filter-options,它适用于第一页加载。每当我尝试以任何方式修改选项时都会遇到问题,正如您将看到的那样,我最初尝试通过 ajax 调用(我可以更改)加载选项,或者如果我需要动态禁用选项,我认为这可能会中断它。

对于第 2 个问题,当我尝试过滤所有这些选项时,需要很长时间,因为每次有人在列表中进行选择时,我都会循环通过所有 7,000 个选项。

这方面的一些指导可能会有所帮助。为了进一步了解这里是我到目前为止的代码:

import React, Component from 'react'
import PropTypes from 'prop-types';
import 'react-select/dist/react-select.css'
import 'react-virtualized/styles.css'
import 'react-virtualized-select/styles.css'
import VirtualizedSelect from 'react-virtualized-select'
import axios from 'axios';

class StockSearch extends Component 
    static propTypes = 
        exchanges: PropTypes.array.isRequired,
        onSelectChange: PropTypes.func.isRequired,
        searchDisabled: PropTypes.bool.isRequired,
        picks: PropTypes.array.isRequired,
        stock_edit_to_show: PropTypes.number
    

    state = 
        stocks: [],
        selected: []
    

    componentWillReceiveProps = (nextProps) => 

    

    /**
     * Component Bridge Function
     * @param stock_id stocks id in the database
     */
    stockSearchChange = (stock_id) => 
        this.props.onSelectChange(stock_id);
    

    componentWillMount = () => 
        this.fetchStocks(this.props.exchanges);
    

    /**
     * Responsible for fetching all of the stocks in the database
     * @param exchanges comma denominated list of exchange ids
     */
    fetchStocks = (exchanges) => 
        let stringExchanges = exchanges.join();
        axios.get('/stock-search-data-by-exchange/', 
            params: 
               exchanges: stringExchanges
            
        )
        .then(response => 
            this.setState(
                stocks: response.data
            )
        )
        .catch(error => 
            console.log(error);
        )
    

    /**
     * handles selected option from the stock select
     * @param selectedOption
     */
    handleSelect = (selectedOption) => 
        this.stockSearchChange(selectedOption.value);
    

    render() 
        return (
            <div className="stock-search-container">
                <VirtualizedSelect
                    name="stock-search"
                    options=this.state.stocks
                    placeholder="Type or select a stock here..."
                    onChange=this.handleSelect
                    disabled=this.props.searchDisabled
                    value=this.props.stock_edit_to_show
                />
            </div>
        )
    


export default StockSearch;

【问题讨论】:

我已经使用原生 很好地处理了 10,000 封电子邮件,加载大约需要半秒,然后过滤是即时的。也许反应代码很慢。尽量不要一次渲染超过 1000 个选项,使用分页或过滤。 见 react-select didn't work for long lists · Issue #2850, react-window 解决方案似乎很有希望 【参考方案1】:

对于问题 #1,react-windowed-select 在类似情况下对我非常有用:https://github.com/jacobworrel/react-windowed-select

对于问题 #2,我发现 react-windowed-select 重绘非常快。你可以用你的数据集试验过滤器,这里有一个代码 sn-p 让你开始:

const startTime = Date.now()

// Create a 7000 element array with a bunch of content, in this case junk strings
array = [...Array(7000)].map(i => Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 5))
const arrayBuiltTime = Date.now()

// Filter out any string with the letter 'q' to emulate a filtering operation
const filteredArray = array.filter(i => !i.includes('q') )
const doneTime = Date.now()

// See how long it takes :-)
console.log(startTime)
console.log(arrayBuiltTime)
console.log(doneTime)

https://codepen.io/smeckman/pen/zYOrjJa?editors=1111

【讨论】:

以上是关于具有非常大的选项列表的 React Select的主要内容,如果未能解决你的问题,请参考以下文章

修复 react-select 下拉列表的高度(React Material UI)

MySQL从具有列名的select语句中的列列表中返回第一个非NULL值

如何使用 React 测试库从选择列表中选择一个选项

从非常大的 Mysql 数据库中获取“文本”列字段的行

用嵌套列表和嵌套字典列表展平一个非常大的 Json

在定义自定义选项组件时,如何为react-select应用默认样式?