T
TanStack3y ago
stormy-gold

Subscribe to specific key changes

In an e-commerce site, I have a cart that gets fetched on every page (globally). I’d like to avoid a useCartQuery() hook on something like the cart icon that only needs to update on a single “itemQuantity” property. I come across this issue on many other instances too where I have a component that only needs to render on a specific item change and not the entire cart. Is there a react-query way of doing this? Can I sync cart with another store that supports selective updates (nanostores/zustand)? I’d also like to avoid prop drilling, and hopefully context.
7 Replies
automatic-azure
automatic-azure3y ago
You can use select option of useQuery to target the quantity. select enables partial subscription to the query
stormy-gold
stormy-goldOP3y ago
Ah, I just discovered “select”. Now if only ts let me infer return type with select options to not have to populate generics
fascinating-indigo
fascinating-indigo3y ago
It does.
stormy-gold
stormy-goldOP3y ago
Sorry, I wasn’t clear. I’m wanting to export a custom hook wrapping react-query and have to use generics according to examples I’ve found. I know I could just do useCartItemCount hook and each case of selection just be specific, but sometimes I just want a one and done without so much boilerplate or ton of generics. In my experience, I can handle personally dealing with generics but sometimes it scares junior devs. lol
automatic-azure
automatic-azure3y ago
you only need to type the select function, which involves one generic only, i.e. the return type
function useCartQuery<T>(select?: (data: Response) => T) {
return useQuery({
queryKey: ["cart"],
queryFn: async () => {
return Promise.resolve({ items: [{ name: "a" }] });
},
select,
});
}

function useCartItemCountQuery() {
return useCartQuery((data) => data.items.length)
}
function useCartQuery<T>(select?: (data: Response) => T) {
return useQuery({
queryKey: ["cart"],
queryFn: async () => {
return Promise.resolve({ items: [{ name: "a" }] });
},
select,
});
}

function useCartItemCountQuery() {
return useCartQuery((data) => data.items.length)
}
stormy-gold
stormy-goldOP3y ago
Using useCartQuery() without select in that example returns unknown type for its data. I keep getting situations like this where I think I solved the riddle but some other edge case breaks. This works
function useCartQuery<T = Cart>(options?: {
select: (data: Cart) => T;
}) {
return useQuery({
queryKey: cartQueryKey,
queryFn: fetchCart,
select: options?.select
});
}
function useCartQuery<T = Cart>(options?: {
select: (data: Cart) => T;
}) {
return useQuery({
queryKey: cartQueryKey,
queryFn: fetchCart,
select: options?.select
});
}
👍
automatic-azure
automatic-azure3y ago
ah nice.. i forgot to default it..

Did you find this page helpful?