reactjs - Får fel när jag hämtar selektorer från createEntityAdapter i Typescript
När jag utvecklade ett enkelt hobbyprojekt stötte jag på ett fel, utan att veta hur jag skulle fixa det. Jag är ny på Typescript, och att döma av ett felmeddelande ligger misstaget i TS. Felmeddelandet visas efter att ha lagt till detta utdrag i filen 'apiSlice.ts'.
export const { selectAll: selectAllPizzas } = pizzasAdapter.getSelectors(
state => selectPizzasData(state) ?? initialState
)
Feltexten ser ut så här:
ERROR in src/features/api/apiSlice.ts:44:31
TS2345: Argument of type 'unknown' is not assignable to parameter of type '{ api: CombinedState<{ getPizzas: QueryDefinition<void, BaseQueryFn<string | FetchArgs, unknown,
FetchBaseQueryError, {}, FetchBaseQueryMeta>, never, PizzaResponseType[], "api">; }, never, "api">; }'.
42 | //
43 | export const { selectAll: selectAllPizzas } = pizzasAdapter.getSelectors(
> 44 | state => selectPizzasData(state) ?? initialState
| ^^^^^
45 | )
46 |
Hela filen: (Fokusera på de sista tre raderna)
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
import { createEntityAdapter, createSelector } from '@reduxjs/toolkit'
const pizzasAdapter = createEntityAdapter()
const initialState = pizzasAdapter.getInitialState()
interface PizzaResponseType {
id: string
name: string
image: string
price: number
currencySign: string
popularityPoint: number
type: string
description: string
spec: string
}
export const apiSlice = createApi({
reducerPath: 'api',
baseQuery: fetchBaseQuery({ baseUrl: '' }),
endpoints: builder => ({
getPizzas: builder.query<PizzaResponseType[], void>({
query: () => '/pizzas',
transformResponse: (responseData: PizzaResponseType[]) => {
pizzasAdapter.setAll(initialState, responseData)
return responseData
},
}),
}),
})
export const { useGetPizzasQuery } = apiSlice
export const selectPizzasResult = apiSlice.endpoints.getPizzas.select()
// console.log(selectPizzasResult)
export const selectPizzasData = createSelector(
selectPizzasResult,
pizzasResult => pizzasResult.data
)
//
export const { selectAll: selectAllPizzas } = pizzasAdapter.getSelectors(
state => selectPizzasData(state) ?? initialState
)
RootState importerades från filen store.ts, där jag konfigurerade butiken som det stod i Redux Toolkit-dokumentationen. Filen store.ts:
const store = configureStore({
reducer: {
pizzas:pizzaSlice,
[apiSlice.reducerPath]: apiSlice.reducer,
},
middleware: getDefaultMiddleware => getDefaultMiddleware().concat(apiSlice.middleware),
})
export type RootState = ReturnType<typeof store.getState>
export default store
Den importerade RootState-typen sattes in för tillståndet i parametern:
export const { selectAll: selectAllPizzas } = pizzasAdapter.getSelectors(
(state: RootState) => selectPizzasData(state) ?? initialState
)
och denna ändring gör inget. Felet visas ändå:
ERROR in src/features/api/apiSlice.ts:46:5
TS2345: Argument of type '(state: RootState) => EntityState<unknown> | PizzaResponseType[]' is not assignable to parameter of type '(state: { pizzas: EntityState<unknown>; api: CombinedState<{ getPizzas: Query
Definition<void, BaseQueryFn<string | FetchArgs, unknown, FetchBaseQueryError, {}, FetchBaseQueryMeta>, never, PizzaResponseType[], "api">; }, never, "api">; }) => EntityState<...>'.
Type 'EntityState<unknown> | PizzaResponseType[]' is not assignable to type 'EntityState<unknown>'.
Type 'PizzaResponseType[]' is missing the following properties from type 'EntityState<unknown>': ids, entities
44 |
45 | export const { selectAll: selectAllPizzas } = pizzasAdapter.getSelectors(
> 46 | (state: RootState) => selectPizzasData(state) ?? initialState
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
47 | )
Hur åtgärdar man det?
Om du vill köra husdjursprojektet. Följ denna länk: https://github.com/AlexKor-5/ReactPizzaApp_Ts/tree/27028d4275fef75a70eb6b0b4b129e5bf5997e78 (men ändra slutet av apiSlice-filen så att det motsvarar filen som visas på den aktuella sidan av Stack Overflow). (src/features/api/apiSlice.ts )
Också när jag skriver <EntityState<PizzaResponseType> hur det ska vara. Titta på exemplet:
getPizzas: builder.query<EntityState<PizzaResponseType>, void>({
query: () => '/pizzas',
transformResponse: (responseData: PizzaResponseType[]) => {
return pizzasAdapter.setAll(pizzaInitialState,responseData)
},
}),
Jag får ett annat fel:
TS2322: Type '(responseData: IPizzaType[]) => EntityState<unknown>' is not assignable to type '(baseQueryReturnV
alue: unknown, meta: FetchBaseQueryMeta | undefined, arg: void) => EntityState<IPizzaType> | Promise<EntityState
<IPizzaType>>'.
Type 'EntityState<unknown>' is not assignable to type 'EntityState<IPizzaType> | Promise<EntityState<IPizzaTyp
e>>'.
Type 'EntityState<unknown>' is not assignable to type 'EntityState<IPizzaType>'.
Type 'unknown' is not assignable to type 'IPizzaType'.
28 | getPizzas: builder.query<EntityState<IPizzaType>, void>({
29 | query: () => '/pizzas',
> 30 | transformResponse: (responseData: IPizzaType[]) => {
| ^^^^^^^^^^^^^^^^^
31 | return pizzasAdapter.setAll(pizzaInitialState, responseData)
32 | },
33 | }),
Vad är det som är fel igen?
Svar #1
Du måste ange en typ för state.
(state: RootState) => selectPizzasData(state) ?? initialState
Svar #2
Följande på @phry:s initiala svar, jag tror problemet är din transformResponse-funktion:
transformResponse: (responseData: PizzaResponseType[]) => {
pizzasAdapter.setAll(initialState, responseData)
return responseData
},
Den koden har ett par problem:
- Du returnerar den ursprungliga
responseData, som fortfarande är enPizzaResponseType[]. Det säger till TS att resultatet också är enPizzaResponseType[], när det som det borde vara är ettEntityState<Pizza>. - För att få det att hända behöver du istället returnera värdet från
pizzasAdapter.setAll().
