Redux Toolkit中带参数useGetUsersQuery返回uninitialized状态的问题
解决RTK Query带参数查询时Selector无法获取数据的问题
核心原因
RTK Query会以调用useGetUsersQuery时传入的参数作为缓存键存储对应数据。你之前定义selectUsersResult = usersApiSlice.endpoints.getUsers.select()时,默认传入undefined作为参数,因此只能匹配调用useGetUsersQuery(undefined)的缓存,无法匹配带参数的查询请求,自然返回uninitialized状态。
动态参数的解决方案
要让Selector跟随参数变化获取对应缓存,需将Selector改为接受动态参数的形式,而非固定值。以下是具体修改步骤:
1. 将查询结果Selector改为函数
把固定的selectUsersResult改成接收参数的函数,根据传入的查询参数返回对应缓存Selector:
// 改为返回Selector的函数,而非固定值 export const selectUsersResult = (queryArgs) => usersApiSlice.endpoints.getUsers.select(queryArgs);
2. 重构数据Selector支持动态参数
利用createSelector支持额外参数的特性,调整selectUsersData让它能接收查询参数并传入底层Selector:
// 支持动态参数的memoized selector const selectUsersData = createSelector( [ (state, queryArgs) => selectUsersResult(queryArgs)(state), ], (usersResult) => { return usersResult.data ?? initialState; } );
3. 调整Entity Adapter的Selector使用方式
由于selectUsersData现在需要查询参数,无法直接用getSelectors创建全局selectUserById,有两种可行方案:
选项A:组件内结合useSelector和动态参数使用
在需要获取单个用户的组件中,传入当前查询参数来获取对应数据集:
const UserDetail = ({ userId, currentQueryParams }) => { const user = useSelector(state => { const usersData = selectUsersData(state, currentQueryParams); return usersAdapter.selectById(usersData, userId); }); return <div>{user?.name}</div>; };
选项B:封装带参数的Selector函数
如果需要复用逻辑,可封装接收查询参数的selectUserById函数:
export const selectUserById = (queryArgs) => (state, userId) => { const usersData = selectUsersData(state, queryArgs); return usersAdapter.selectById(usersData, userId); }; // 组件内调用示例: const user = useSelector(state => selectUserById({page:1, limit:10})(state, userId));
4. 修复原代码的额外问题
你原代码中getUsers的query函数未使用传入的args,导致无论传什么参数,请求都是固定的page=1&limit=10,会引发参数不同但缓存被覆盖的问题,需修正:
getUsers: builder.query({ query: (args = { page:1, limit:10 }) => { // 设置默认值,兼容不传参数的场景 return { url: `/api/users/`, method: "GET", params: args, // 使用传入的参数 } }, // ...其他配置保持不变 }),
组件内正确调用示例
const UserList = () => { const queryParams = { page: 1, limit: 10 }; const { data: users } = useGetUsersQuery(queryParams); // 组件内直接用adapter方法通过ID获取用户 const getUserById = (id) => usersAdapter.selectById(users ?? initialState, id); return <div>user table</div>; };
内容的提问来源于stack exchange,提问作者wilker0725
相关产品推荐
相关产品推荐

