我一直在遵循REDUX要点指南,现在是第8部分,将RTK查询与createEntityAdapter
相结合。我使用指南在一个个人项目中实现它,其中我的getUni
端点有一个名为country
的参数,如下面的代码片段所示。
我想知道是否有任何方法可以从代码段底部的universityAdaptor.getSelector(state => )
中的状态访问country
参数值,因为查询键名不断变化。
import {
createEntityAdapter,
createSelector,
nanoid
} from "@reduxjs/toolkit";
import {
apiSlice
} from "../api/apiSlice";
const universityAdapter = createEntityAdapter({})
const initialState = universityAdapter.getInitialState();
export const extendedApiSlice = apiSlice.injectEndpoints({
endpoints: builder => ({
getUni: builder.query({
query: country => ({
url: `http://universities.hipolabs.com/search?country=${country}`,
}),
transformResponse: responseData => {
let resConvert = responseData.slice()
.sort((a, b) => a.name.localeCompare(b.name))
.map(each => {
return { ...each,
id: nanoid()
}
});
return universityAdapter.setAll(initialState, resConvert)
}
})
})
});
export const {
useGetUniQuery
} = extendedApiSlice;
export const {
selectAll: getAllUniversity
} = universityAdapter.getSelectors(state => {
return Object.keys({ ...state.api.queries[<DYNAMIC_QUERY_NAME>]data }).length === 0
? initialState : { ...state.api.queries[<DYNAMIC_QUERY_NAME>]data }
})
更新:由于RTK查询处理抓取时创建的多个redux操作,我让它与转弯操作符一起工作。想知道这是否是最佳实践,因为我仍然没有弄清楚如何访问country
参数。
export const { selectAll: getAllUniversity } = universityAdapter
.getSelectors(state => {
return !Object.values(state.api.queries)[0]
? initialState : Object.values(state.api.queries)[0].status !== 'fulfilled'
? initialState : Object.values(state.api.queries)[0].data
})
我写了"必需品";教程:)
我实际上有点困惑你的问题是什么-你能说清楚你具体想做什么吗?
话虽如此,我还是会尽量提供一些相关的信息。
首先,您不需要在大多数时间内手动调用someEndpoint.select()
-相反,调用const { data } = useGetThingQuery("someArg")
, RTKQ将获取并返回它。你只需要调用someEndpoint.select()
,如果你手动构造一个选择器在其他地方使用。
someEndpoint.select()
的要点是构造"一个选择器,该选择器将返回该缓存键的整个缓存条目"。通常,您希望从缓存项中获取的只是接收值,该值存储为cacheEntry.data
,在本例中,它将包含从transformResponse()
返回的规范化{ ids : [], entities: {} }
查找表。
理论上,你可以这样做:
const selectNormalizedPokemonData = someApi.endpoints.getAllPokemon.select();
// These selectors expect the entity state as an arg,
// not the entire Redux root state:
// https://redux-toolkit.js.org/api/createEntityAdapter#selector-functions
const localizedPokemonSelectors = pokemonAdapter.getSelectors();
const selectPokemonEntryById = createSelector(
selectNormalizedPokemonData ,
(state, pokemonId) => pokemonId,
(pokemonData, pokemonId) => {
return localizedPokemonSelectors.selectById(pokemonData, pokemonId);
}
)
一些更多的信息,可能有助于了解发生了什么与要领教程中的代码,后台- getLists端点接受1个参数,选择在服务:
export const getListsResult = (state: RootState) => {
return state.tribeId ? extendedApi.endpoints.getLists.select(state.tribeId) : [];
};
和切片中的选择器:
export const selectAllLists = createSelector(getListsResult, (listsResult) => {
console.log('inside of selectAllLists selector = ', listsResult);
return listsResult.data;
// return useSelector(listsResult) ?? [];
});
现在这个控制台将listsResult
记录为ƒ memoized() {
功能!不能像教程建议的那样拥有.data
属性。此外,return useSelector(listsResult)
-通过执行记忆函数使其工作。
这是我得到了多远,但从我的理解,在要领教程中的代码不工作,因为它是…
但是到这里https://codesandbox.io/s/distracted-chandrasekhar-r4mcn1?file=/src/features/users/usersSlice.js并添加相同的控制台日志:
const selectUsersData = createSelector(selectUsersResult, (usersResult) => {
console.log("usersResult", usersResult);
return usersResult.data;
});
显示它返回的不是一个记忆函数,而是一个带有数据的对象。
不知道是否因为我在端点上有一个参数而发生差异…
select
返回一个记忆的curry函数。因此,首先使用相应的参数(在您的示例中称为tribeId
)调用它,然后使用state
。这将为相应的链式选择器返回result
对象。
export const getListsResult = (state: RootState) => {
return state.tribeId ? extendedApi.endpoints.getLists.select(state.tribeId)(state) : [];
};
getUni
端点的目的是生成一个大学数据数组。为了实现.getSelector
函数来检索该数组,我循环遍历所有查询值,搜索getUni
查询并确保它们是fulfilled
。底部转弯操作符确认getUni
端点至少被触发一次,否则返回initialState
值。
export const { selectAll: getAllUniversity } = universityAdapter
.getSelectors(state => {
let newObj = {};
for (const value of Object.values(state.api.queries)) {
if (value?.endpointName === 'getUni' && value?.status === 'fulfilled') {
newObj = value.data;
}
}
return !Object.values(newObj)[0] ? initialState : newObj;
})