如何在RTK Query选择器中使用参数?数据不显示问题排查
问题根源
你的核心问题是:RTK Query会为每个不同的查询参数创建独立的缓存条目,但你的全局选择器始终只读取「无debouncedQuery参数」时的缓存数据,搜索后的新结果存在另一个缓存条目里,导致selectItemById找不到对应id。
解决方案
提供两种可行方案,按需选择:
方案一:修改选择器,支持查询参数匹配
1. 调整Item ApiSlice中的选择器定义
让选择器能接收查询参数,定位到对应缓存条目:
const itemsAdapter = createEntityAdapter<Item>() const initialState = itemsAdapter.getInitialState(); // ... 其他代码不变 // 改成接收查询参数的函数,定位对应缓存 export const selectItemsResult = (queryArg: string | undefined) => itemApiSlice.endpoints.filterItems.select(queryArg); // 创建带参数的选择器工厂 const createSelectItemsData = (queryArg: string | undefined) => createDraftSafeSelector( selectItemsResult(queryArg), itemsResult => itemsResult.data ?? initialState ); // 生成带参数的selectItemById选择器 export const createSelectItemById = (queryArg: string | undefined) => { const selectItemsData = createSelectItemsData(queryArg); return (state: RootState, id: EntityId) => { const itemsState = selectItemsData(state); return itemsAdapter.selectById(itemsState, id); }; };
2. 修改ItemDetail组件,接收查询参数并使用对应选择器
// 新增queryArg参数 export function ItemDetail(props: ItemProps & { queryArg: string | undefined }) { const {index, id, onSelectedItem, queryArg} = props; // 根据查询参数动态生成选择器 const selectItemById = useMemo(() => createSelectItemById(queryArg), [queryArg]); const item = useAppSelector(state => selectItemById(state, id)); // ... 其余代码不变 }
3. 在SearchItem组件中传递查询参数
{ids.map((itemId: EntityId, index: number) => { return <ItemDetail key={index} index={index} id={itemId} onSelectedItem={onSelectedItem} queryArg={debouncedQuery} // 传入当前的debounced查询参数 /> })}
方案二:直接传递Item数据(更简单)
既然SearchItem组件已经通过useFilterItemsQuery拿到了完整的entity状态,直接在组件内获取Item数据并传递给ItemDetail,跳过全局选择器:
1. 修改SearchItem组件的渲染逻辑
{ids.map((itemId: EntityId, index: number) => { // 直接在当前组件内用adapter获取item const item = itemsAdapter.selectById(items!, itemId); return <ItemDetail key={index} index={index} item={item} // 直接传递item数据 onSelectedItem={onSelectedItem} /> })}
2. 调整ItemDetail组件的参数
// 去掉id参数,直接接收item export function ItemDetail(props: Omit<ItemProps, 'id'> & { item: Item }) { const {index, item, onSelectedItem} = props; // 无需再用useAppSelector获取数据 console.log("item: ", item); const handleOnClickedItem = () => { onSelectedItem(item); } // ... 其余渲染代码不变,把所有item?.改为item.即可 }
内容的提问来源于stack exchange,提问作者Ntezi
相关产品推荐
相关产品推荐

