如何用react-bootstrap-typeahead实现多异步数据源分组搜索?
可以实现多异步数据源的分组展示需求
完全能用react-bootstrap-typeahead实现你要的多数据源分组展示效果,核心思路是在onSearch中并行处理多个异步请求,给每个数据源的结果打上分组标识,过滤空结果后传给组件,利用组件的分组能力渲染即可。
具体实现步骤:
并行处理多数据源请求
在onSearch函数里,用Promise.all同时发起地址数据库查询和本地历史搜索过滤(历史搜索如果是同步数据,用Promise.resolve包装统一流程),确保多个请求并行执行提升效率。给结果打分组标识并过滤空数据
每个数据源返回结果后,给每条数据添加group字段(比如"地址"、"历史搜索"),同时只保留有结果的数据源,避免空分组展示。利用组件分组能力渲染
通过groupBy属性指定分组字段,组件会自动按分组展示结果;如果需要自定义分组样式,用renderMenu和renderGroup做定制。
代码示例:
import { useState } from 'react'; import { Typeahead, TypeaheadMenuItem } from 'react-bootstrap-typeahead'; import 'react-bootstrap-typeahead/css/Typeahead.css'; const SearchBox = () => { const [options, setOptions] = useState([]); const [isLoading, setIsLoading] = useState(false); // 模拟地址数据库查询 const fetchAddresses = async (query) => { const res = await fetch(`/api/addresses?q=${query}`); return res.json(); }; // 从store获取过滤后的历史搜索 const getHistorySearches = (query) => { const history = window.store.getState().searchHistory; return history.filter(item => item.label.toLowerCase().includes(query.toLowerCase())); }; const handleSearch = async (query) => { if (!query.trim()) { setOptions([]); return; } setIsLoading(true); // 并行处理两个数据源,用allSettled避免单个请求失败导致全部失败 const results = await Promise.allSettled([ fetchAddresses(query), Promise.resolve(getHistorySearches(query)) ]); const groupedOptions = []; // 处理地址查询结果 const addressResult = results[0]; if (addressResult.status === 'fulfilled' && addressResult.value.length > 0) { groupedOptions.push( ...addressResult.value.map(item => ({ ...item, group: '地址' })) ); } // 处理历史搜索结果 const historyResult = results[1]; if (historyResult.status === 'fulfilled' && historyResult.value.length > 0) { groupedOptions.push( ...historyResult.value.map(item => ({ ...item, group: '历史搜索' })) ); } setOptions(groupedOptions); setIsLoading(false); }; return ( <Typeahead onSearch={handleSearch} options={options} isLoading={isLoading} groupBy="group" labelKey="label" placeholder="输入关键词搜索..." // 自定义分组头部样式 renderGroup={(group, items) => ( <div className="group-header"> <strong>{group}</strong> </div> )} /> ); }; export default SearchBox;
关键注意点:
- 用
Promise.allSettled替代Promise.all,可以避免某个数据源请求失败时,整个搜索流程中断。 - 确保每个数据源的结果都包含
label字段(或通过labelKey指定其他字段),组件才能正确渲染选项文本。 - 如果本地历史搜索是同步数据,用
Promise.resolve包装后可以和异步请求统一处理逻辑,代码更简洁。
内容的提问来源于stack exchange,提问作者Nighto
相关产品推荐
相关产品推荐

