2

I've been creating React Typescript app with RTK Query, and I want to implement custom selectors. But to implement it, I need to get some data from another endpoint:

store.dispatch(userApiSlice.endpoints.check.initiate(undefined))
const data = userApiSlice.endpoints.check.getSomeData

export const selectCartItemsResult = cartApiSlice.endpoints.getCartItems
  .select(data?.user?.id ?? skipToken)

I found solution here. Their solution looks like this:

class TodoService {
   getSelectorForTodo(todoId: string) {
     if (this._lastId !== todoId) 
       this._lastSelector = api.endpoints.getTodo.select( {id: todoId } )
     return this._lastSelector
   }

   getTodoTitle( todoId: string ) {
     const todo = this.getSelectorForTodo(todoId)(state)
     return todo.data.title
   }
}

I do not where to get the state variable. So I come with putting inside store.getState(), but this gives the following error:

const data = userApiSlice.endpoints.check
  .select(undefined)(store.getState())

-->

The types of 'api.queries' are incompatible between these types. Type 'QueryState<{ getCartItems: QueryDefinition<number, BaseQueryFn<string | FetchArgs, unknown, FetchBaseQueryError, {}, FetchBaseQueryMeta>, "cart", EntityState<...>, "api">; clearCart: MutationDefinition<...>; addItem: MutationDefinition<...>; changeItemQuantity: MutationDefinition<...>; changeItemSize: MutationDefini...' is not assignable to type 'QueryState<{ registration: MutationDefinition<IRegisterBody, BaseQueryFn<string | FetchArgs, unknown, FetchBaseQueryError, {}, FetchBaseQueryMeta>, "cart", IUserApiState, "api">; login: MutationDefinition<...>; check: QueryDefinition<...>; }>'.

I don't have another idea of how to get a state variable. Please, can you give some example that compiles with typescript but also declares the state variable?

I do not know what you need of all RTK Query implementation. So I will add it when needed

EDIT: cartApiSlice and userApiSlice were created with injectEndpoints.

2
  • is this userApiSlice injected with injectEndpoints? Commented Oct 11, 2022 at 9:19
  • Yes, userApiSlice and cartApiSlice were created with injectEndpoints Commented Oct 11, 2022 at 9:23

2 Answers 2

2

Because your userApiSlice was injected into your api after your state was created, TypeScript can't know that something was added here - so it complains because the api "in the types" just doesn't have those extra endpoints.

That doesn't mean that it won't work though - it's just that TypeScript is complaining here.

You won't get around telling TypeScript "I know better than you" in this case - do an assertion as any.

const data = userApiSlice.endpoints.check
  .select(undefined)(store.getState() as any)
Sign up to request clarification or add additional context in comments.

9 Comments

I do like this: store.dispatch(userApiSlice.endpoints.check.initiate(undefined)) .unwrap().catch(() => undefined) export const all = userApiSlice.endpoints.check .select(undefined)(store.getState() as any) all in debugger shows: endpointName: 'check' isError: false isLoading: true isSuccess: false isUninitialized: false requestId: 'stG-BTk2dgU41MaGCWXcm' startedTimeStamp: 1665573056482 status: 'pending'
Your code runs once and gets you a snapshot of the data at that time. You will need to add code subscribing to store changes and re-executing the selector every time that happens if you want that - that's what react-redux usually does for you.
A subscription in the context of RTKQ means "someone is using that data right now, don't delete it from the cache until they unsubscribe". It won't magically update your variables for you. You want store.subscribe which will allow you to run a selector on every store change. Or, really, try to do this closer to a component or run the selector when you need that data.
What does that in the context of react-redux is useSelector. It subscribes to the store and rerenders the component on each change.
Sorry I'm really not up for chatting right now. I would suggest you ask in the redux channel on the Reactiflux Discord as there are always people helping out there.
|
0

You can do it with something like:

import { userApi } from 'src/app-redux/services/userAPI';
import { store } from 'src/app-redux/store';

.
.

// Adding a cache subscription
const promise = store.dispatch(userApi.endpoints.getSomeData.initiate('hello'));
const { refetch } = promise;
// interact with the cache in the same way as you would with a useFetch...() hook
const { data, isLoading, isSuccess /*...*/ } = await promise;

// do stuff with data

// Removing the corresponding cache subscription
promise.unsubscribe();

.
.

As mentioned in the official docs: https://redux-toolkit.js.org/rtk-query/usage/usage-without-react-hooks

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.