如何在Redux-Toolkit Query的选择器中使用带参数的查询?
如何在Redux-Toolkit Query的选择器中使用带参数的查询?
我完全懂你的困惑!带参数的RTK Query端点在配合Redux选择器使用时,确实和无参数的情况不一样——核心原因是你没搞清楚RTK Query的select方法到底在做什么。
先理清楚本质
RTK Query的endpoints.[name].select(param)其实是一个选择器工厂函数:它接收你的查询参数,返回一个新的Redux选择器,这个选择器可以从store中取出该参数对应的查询结果。你之前尝试在createSelector的回调里直接调用它,相当于每次都会生成新的选择器,破坏了createSelector的memoization(缓存)机制,所以行不通。
针对你场景的解决方案(orgId来自Store)
既然你的orgId是从store里通过getOrgId选择器获取的,我们可以把state也作为createSelector的输入之一,然后在回调里根据orgId生成对应的查询选择器,再用state获取结果:
import { createSelector } from '@reduxjs/toolkit'; import { apiSlice } from './apiSlice'; import { getOrgId } from './orgSlice'; // 假设这是你的orgId选择器 export const getAccountsResult = createSelector( // 输入选择器:同时获取orgId和整个store的state [getOrgId, (state) => state], (orgId, state) => { // 根据orgId生成查询选择器,再传入state拿到结果 const accountsQueryResult = apiSlice.endpoints.getAccounts.select(orgId)(state); // 兼容数据未加载/请求失败的情况 return accountsQueryResult.data || []; } );
这样写的好处是完全保留了createSelector的memoization特性:只有当orgId或者对应的查询结果变化时,才会重新计算返回值,不会浪费性能。
灵活方案(orgId来自组件Props)
如果你的orgId是来自组件的props(而非store),可以创建一个选择器工厂函数,在组件里动态生成选择器:
export const makeGetAccountsResult = () => createSelector( [(state, props) => props.orgId, (state) => state], (orgId, state) => { const accountsQueryResult = apiSlice.endpoints.getAccounts.select(orgId)(state); return accountsQueryResult.data || []; } ); // 在组件里使用(配合useMemo避免重复生成选择器) const accounts = useSelector((state) => makeGetAccountsResult()(state, { orgId: currentOrgId }));
关于“我是否应该这么用RTK Query?”
视场景而定:
- RTK Query的核心设计目标是让你在组件里通过hooks(比如
useGetAccountsQuery)直接获取数据,自动处理缓存、请求重试、过期重取等逻辑,大部分业务场景下用hooks就足够了。 - 但如果你需要在跨slice的复杂数据计算、middleware/saga里访问数据,或者多个组件共享衍生数据逻辑时,像这样用选择器访问RTK Query的缓存是完全合理的,RTK Query官方文档也明确支持这种用法。
小技巧:用selectFromResult简化代码
你可以用RTK Query提供的selectFromResult辅助函数来简化查询结果的处理:
// 先定义一个处理查询结果的辅助选择器 const selectAccountsData = apiSlice.endpoints.getAccounts.selectFromResult( (result) => result.data || [] ); // 然后在之前的createSelector里使用 export const getAccountsResult = createSelector( [getOrgId, (state) => state], (orgId, state) => { // 生成带参数的查询选择器,再传入state,最后用辅助选择器提取数据 const querySelector = apiSlice.endpoints.getAccounts.select(orgId); return selectAccountsData(querySelector(state)); } );
内容来源于stack exchange
相关产品推荐
相关产品推荐

