2

So, I am using a selector-esque with react-query and I am getting an error when I try to pluck some values off of the cache.

Here is the error I am getting: TS2339: Property 'phone' does not exist on type 'QueryObserverResult '.

  1. Whats the "type" of select here?

here is the cache mutation:

export default function useProductCache (select: ?): QueryObserverResult<Product, Error> {
  const queryClient = useQueryClient();

  return useQuery(
    queryKey,
    async () => {
      const product = await queryClient.getQueryData(queryKey);

      return product;
    },
    { select }
  );
}

And here is where I create the "selector-esque" function:

export const useProductByKeysSelector = (keys: string[]) => useProductCache((data: Product) => {
  const objectByKeys = keys.reduce<Record<string, any>>((byKeys, k) => {
    byKeys[k] = get(data, k);
   
    return byKeys;
  }, {})

  return objectByKeys;
})

So, "phone" IS on Product. But its still giving me an error (as noted above)?

What if I wanted to "add" a custom key in the return, how would I type that?

1 Answer 1

1

The type of select is a function from whatever your queryFn returns (Product) to whatever your hook should in the end return:

select: (data: Product) => TResult

But the end result must appear in the type of QueryObserverResult. You could also get rid of the QueryObserverResult typing and let type inference do it’s work.

I’m not really sure what you are trying to achieve though. Why create a query that just reads from the query cache? getQueryData is synchronous…

Sign up to request clarification or add additional context in comments.

3 Comments

I was just wanted to create a hook that read from the "cache" of any particular query. Are you saying there is no reason to wrap it in a useQuery? Doesn't that enable us to sorta get the same return ala, ,isLoading, etc... or I can just use: const product = queryClient.getQueryData(queryKey); ? and that does the same thing?
I figured it would make more sense to "get the cache" than keep hitting the server for my product (if I already got it) and be able to use "select". No? Also, when creating "selectors-esque" items, aren't I always calling the useQuery.. seems I can circumvent that by just returrning the cache than actually using the "real" query. Is it a bad pattern I'm using? Just seemed redundant to add useQuery('whatever'l.) in every "selector" type.
The preferred approach is to create a custom useProduct hook and just call it every time when you need the data. Sure, you can pass a selector to it (useProduct(p => p.something)) and it will kinda act like useSelector from redux. I assume you just want to read from the cache and not hit the backend every time, which is what setting a custom staleTime is usually for. As long as a query is not stale (=fresh), data will always come from the cache with useQuery and no request (background update) is made.

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.