1

I have a query with argument that can be an object or undefined. When I use function selectFromResult in my component, the endpoint is called with argument of undefined.

I understood that it should just get the value from the existing data not call the endpoint with no parameters.

export const getMessages = (
  build: EndpointBuilder<BaseQueryFn, string, string>
): QueryDefinition<
  IGetMessagesArgs | undefined,
  BaseQueryFn,
  string,
  IGetMessagesResponse
> =>
  build.query<IGetMessagesResponse, IGetMessagesArgs | undefined>({
    providesTags: ['Message'],
    query: (queryArg: IGetMessagesArgs | undefined) => {
      const paginationParamObject = {
        conversation: queryArg?.conversation,
        page: queryArg?.page,
      };
      const paginationQuery = serializeFlatObject(paginationParamObject, '?');
      const filterQuery = serializeFilters(queryArg?.filters);
      return {
        url: `/api/messages${paginationQuery}${filterQuery}`,
      };
    }
  });

In the parent component I'm calling it like this

const { data: messages } = useGetMessagesQuery(
    { conversation: conversation || '' },
    { skip: !conversation }
  );

And in the detials component

 const { message } = useGetMessagesQuery(undefined, {
    selectFromResult: ({ data }) => ({
      message: data?.items.find((el) => el.id === messageId),
    }),
  });

Is selectFromResult used wrong in this case?

user3463645
  • 126
  • 1
  • 10

1 Answers1

3

selectFromResult just allows you to change the shape of result by using a selector function.
But besides that, useGetMessagesQuery still works like useGetMessagesQuery works - no changes. So if you call useGetMessagesQuery with an undefined argument, it will start a request for an undefined argument.

Your impression seems to be that once you add selectFromResult, it will just give you the result of a random cache entry for that endpoint - that is not the case.

phry
  • 35,762
  • 5
  • 67
  • 81
  • 1
    Ok, got it. I must have understood it wrong then. I was reading this part from the doc https://redux-toolkit.js.org/rtk-query/usage/queries#selecting-data-from-a-query-result It says: "In most cases you don't want to perform an additional request for a getItemById-type query when you know that you already have the result." – user3463645 Apr 09 '22 at 20:02
  • 1
    I also was confused by the same point. @phry Is there no way to access the value from query in a child component? This line makes me think, I should be able to access the value from the cache/store `In most cases you don't want to perform an additional request for a getItemById-type query when you know that you already have the result`, but what you mentioned above contradicts this. And in my code, I receive undefined for the result in my child component. That as something like `const cachedData = useGetBySheedIdQuery(skipToken, { selectFromResult: ({data}) => ({data})}) – adam.k Jun 23 '22 at 06:42
  • It looks like I was confused about what `skipToken` does as well. Reading more, is the only way to access the cached result is provide the same parameters to the hook? In the parent component I'd use `useGetSheetById('1234')`, then if I were to use the same hook and id in some child component `useGetSheetById('1234')` this would access the cache instead of making a new query. Testing locally this seems to be the case. Could you please point me to documentation if there is another way to do this. Ideally I'd like to be able to access the cache in similar way I can access a redux store – adam.k Jun 23 '22 at 06:57
  • 2
    @adam.k To access a cache entry you need the exact same arguments as you used for starting the query - you could have 20 components mounted and every single one of them could be firing a different query; you need to be able to select one of them. You can always have that argument you pass into your query in your Redux store. – phry Jun 23 '22 at 07:17