如何使用RTK Query实现搜索与筛选功能?
基于RTK Query的搜索筛选最优实现方案
你的初始方案是否可行?
完全可行。把缓存数据存入本地状态(比如React的useState),筛选时更新状态变量展示结果、取消筛选时重置为原始缓存数据,这种方式逻辑简单,适合小型数据集场景。但缺点是需要手动同步缓存更新——如果RTK Query的缓存因重新请求、失效等原因更新,你得手动把新数据同步到本地状态,否则会出现展示数据和缓存不一致的问题。
基于RTK Query的更优实现方式
推荐直接在组件中基于RTK Query返回的原始缓存数据做实时筛选,无需额外维护本地状态,利用RTK Query的缓存特性自动同步数据更新:
1. 基础实时筛选实现
用useQuery获取原始数据,结合本地搜索状态(比如useState存搜索关键词),在渲染阶段直接对原始数据进行筛选:
import { useGetItemsQuery } from './apiSlice'; import { useState } from 'react'; function ItemList() { const [searchTerm, setSearchTerm] = useState(''); const { data: allItems = [], isLoading } = useGetItemsQuery(); // 实时生成筛选结果 const filteredItems = allItems.filter(item => item.name.toLowerCase().includes(searchTerm.toLowerCase()) ); if (isLoading) return <div>加载中...</div>; return ( <> <input type="text" value={searchTerm} onChange={(e) => setSearchTerm(e.target.value)} placeholder="搜索物品..." /> <button onClick={() => setSearchTerm('')}>取消筛选</button> <ul> {filteredItems.map(item => ( <li key={item.id}>{item.name}</li> ))} </ul> </> ); }
这种方式的优势:
- 无需手动同步缓存,RTK Query缓存更新时,
allItems会自动刷新,筛选结果也会实时同步 - 代码简洁,减少状态维护成本
- 适配大多数中小型数据集场景
2. 大型数据集优化:用RTK Query的select选项
如果数据集很大,每次渲染都执行filter会有性能开销,可以利用useQuery的select选项,让RTK Query在缓存层完成筛选,只返回符合条件的结果:
import { useGetItemsQuery } from './apiSlice'; import { useState, useMemo } from 'react'; function ItemList() { const [searchTerm, setSearchTerm] = useState(''); // 用useMemo缓存筛选函数,避免不必要的缓存重新计算 const selectFilteredItems = useMemo(() => { return (data) => { if (!searchTerm) return data; return data.filter(item => item.name.toLowerCase().includes(searchTerm.toLowerCase()) ); }; }, [searchTerm]); const { data: filteredItems = [], isLoading } = useGetItemsQuery( undefined, // 若你的query无需参数,此处传undefined { select: selectFilteredItems } ); if (isLoading) return <div>加载中...</div>; return ( <> <input type="text" value={searchTerm} onChange={(e) => setSearchTerm(e.target.value)} placeholder="搜索物品..." /> <button onClick={() => setSearchTerm('')}>取消筛选</button> <ul> {filteredItems.map(item => ( <li key={item.id}>{item.name}</li> ))} </ul> </> ); }
select选项的作用是对RTK Query返回的缓存数据做转换后再传给组件,好处是:
- 筛选逻辑在RTK Query内部处理,组件只需关注最终结果
- 配合
useMemo缓存select函数,避免每次搜索词变化触发不必要的缓存计算
3. 多条件筛选扩展
如果需要多条件筛选(比如按类别、价格范围),只需扩展本地状态和筛选逻辑即可,无论是基础方式还是select方式都能轻松适配:
// 多条件筛选示例(基础方式) const [filters, setFilters] = useState({ searchTerm: '', category: 'all', minPrice: 0 }); const filteredItems = allItems.filter(item => { const matchesSearch = item.name.toLowerCase().includes(filters.searchTerm.toLowerCase()); const matchesCategory = filters.category === 'all' || item.category === filters.category; const matchesPrice = item.price >= filters.minPrice; return matchesSearch && matchesCategory && matchesPrice; });
方案选择建议
- 数据集小、筛选逻辑简单:用基础实时筛选方式,代码量最少,维护成本低
- 数据集大、追求性能:用RTK Query的select选项,减少组件端计算开销
- 需要复杂筛选状态管理(比如保存筛选条件到URL、持久化筛选状态):可以结合
useState或Redux本地状态管理筛选条件,再配合上述两种筛选方式
内容的提问来源于stack exchange,提问作者Derek emmanuel
相关产品推荐
相关产品推荐

