下拉,搜索,接口搜索,配置化(初始化,非初始化),为空搜索,根据值搜索,loding,选项配置

  1. 支持用户输入时异步加载选项(带防抖)

  2. 可配置防抖时间

  3. 支持设置默认选项

  4. 可以控制是否在空值时加载数据

  5. 支持在组件挂载时加载初始数据

  6. 支持在聚焦时自动加载数据(当满足条件时)

  7. data: 存储从异步请求获取的选项

  8. value: 当前选中的值

  9. loading: 加载状态

  10. 使用useRef来存储当前搜索值(currentSearchRef)和定时器(timeoutRef

  11. loadData(searchValue): 负责发起异步请求,使用防抖控制请求频率。在请求返回后,会检查当前搜索值是否与发起请求时一致,避免竞态条件。

  12. handleSearch(newValue): 处理搜索输入变化,根据loadOnEmpty配置决定是否在空值时加载数据。

  13. handleChange(newValue): 处理选择值变化。

  14. 使用useEffect在组件挂载时执行初始加载(如果initialLoad为true),并在卸载时清除定时器。

  15. ​防抖控制​​:有效减少请求次数,提升性能。

  16. ​竞态处理​​:通过引用记录当前搜索值,避免因请求返回顺序导致的显示错误。

  17. ​配置灵活​​:提供多个配置项(如debounceTimeloadOnEmptyinitialLoad)满足不同场景需求。

  18. ​内存管理​​:在组件卸载时清除定时器,避免内存泄漏。

  19. ​空值处理​​:通过loadOnEmpty控制空搜索时的行为,使组件更灵活。

import React, { useState, useEffect, useRef } from 'react';
import { Select } from 'antd';

const SearchSelect = (props) => {
    const {
        fetchData,
        style,
        placeholder,
        defaultOptions = [],
        debounceTime = 500,
        loadOnEmpty = true, // 新增:是否在空值时加载数据
        initialLoad = false // 新增:是否在组件挂载时加载初始数据
    } = props;

    const [data, setData] = useState([]);
    const [value, setValue] = useState();
    const [loading, setLoading] = useState(false);
    const currentSearchRef = useRef();
    const timeoutRef = useRef();

    // 加载数据函数
    const loadData = (searchValue) => {
        // 记录当前搜索值
        currentSearchRef.current = searchValue;
        setLoading(true);

        // 清除之前的定时器
        if (timeoutRef.current) {
            clearTimeout(timeoutRef.current);
        }

        // 设置新的定时器
        timeoutRef.current = setTimeout(() => {
            fetchData(searchValue || '', (result) => {
                // 确保返回的数据对应的是当前搜索值
                if (currentSearchRef.current === searchValue) {
                    setData(result);
                    setLoading(false);
                }
            });
        }, debounceTime);
    };

    // 处理搜索
    const handleSearch = (newValue) => {
        // 如果允许空值搜索,或者有搜索值
        if (loadOnEmpty || newValue) {
            loadData(newValue);
        } else {
            // 如果不允许空值搜索且搜索值为空,则清空数据
            setData([]);
        }
    };

    // 处理值变化
    const handleChange = (newValue) => {
        setValue(newValue);
    };

    // 组件挂载时加载初始数据
    useEffect(() => {
        if (initialLoad) {
            loadData('');
        }

        // 组件卸载时清除定时器
        return () => {
            if (timeoutRef.current) {
                clearTimeout(timeoutRef.current);
            }
        };
    }, []);

    return (
        <Select
            showSearch
            value={value}
            placeholder={placeholder}
            style={style}
            defaultActiveFirstOption={false}
            suffixIcon={null}
            filterOption={false}
            onSearch={handleSearch}
            onChange={handleChange}
            notFoundContent={loading ? "搜索中..." : "无匹配数据"}
            loading={loading}
            options={[...defaultOptions, ...data]}
            onFocus={() => {
                // 当聚焦时,如果允许空值搜索且当前没有数据,则加载数据
                if (loadOnEmpty && data.length === 0) {
                    loadData('');
                }
            }}
        />
    );
};


// 定义默认属性值
SearchSelect.defaultProps = {
    style: null,
    placeholder: '请选择',
    defaultOptions: [],
    debounceTime: 500,
    loadOnEmpty: true,
    initialLoad: false
};

export default SearchSelect;

更多推荐