T
TanStack11mo ago
like-gold

How to enable a query for a specific query param

I have a GET endpoint, in which the values for the query params are passed in as arguments to the query, e.g.
function useGetItems(debouncedQuery: string, id?: string) {
return useQuery({
queryKey: ['items', { debouncedQuery, ...(id && { id }) }],
queryFn: async () => {
try {
const response = await axios.get<Item[]>(`${ITEM_LOOKUP_ENDPOINT}/search`, {,
params: {
item: debouncedQuery,
...(id && { id }),
},
})

if (id !== undefined) {
return response.data
}

return response.data.filter(item => item.description.toLowerCase().includes(debouncedQuery.toLowerCase()))
} catch (e) {
throw new Error(e instanceof Error ? e.message : 'Item not found')
}
},
enabled: () => {
if (id !== undefined) {
return !!id
}

return !!debouncedQuery
},
})
}
function useGetItems(debouncedQuery: string, id?: string) {
return useQuery({
queryKey: ['items', { debouncedQuery, ...(id && { id }) }],
queryFn: async () => {
try {
const response = await axios.get<Item[]>(`${ITEM_LOOKUP_ENDPOINT}/search`, {,
params: {
item: debouncedQuery,
...(id && { id }),
},
})

if (id !== undefined) {
return response.data
}

return response.data.filter(item => item.description.toLowerCase().includes(debouncedQuery.toLowerCase()))
} catch (e) {
throw new Error(e instanceof Error ? e.message : 'Item not found')
}
},
enabled: () => {
if (id !== undefined) {
return !!id
}

return !!debouncedQuery
},
})
}
I only need to filter on the first query param, which is item , which will display an array of items which can be narrowed down further with the id query param. Another API call would be required if the id query param has a value, which will then return an array of items, which can no longer be narrowed down. An example would be, a user searches for console. The item query param will be console and in the response, you may find an object with a description property of "Nintendo - Switch, Wii U, Wii", and also has an id property. If the user selects this option, then the value id is passed into the id query param and a new list of items gets rendered. This time with the individual item. I thought of using the refetch function, but it doesn't permit arguments being passed in. What would be a good way to go about this?
1 Reply
absent-sapphire
absent-sapphire11mo ago
This one seems to have a couple layers to me but if I was approaching this I'd probably think of it this way: I'd start off by saying that on each change of the queryKey, it will do another queryFn call so I think the issue is more of the structure of this useQuery. It feels like to me that you are accounting for the following issues: 1. Listing out all items 2. Listing out items by a search query 3. Listing out items by an id I'd probably separate these out into three separate hooks of useGetItems, useSearchItems, and useItem (by id). Sidenote, I'd take a look at this blog post regarding effective keys: https://tkdodo.eu/blog/effective-react-query-keys. If you would like to keep them more together in one hook, I think it is possible but I'd avoid filtering the results within the try catch, and rather use the select feature of useQuery which you can pass as a function to the useGetItems hook to filter after the call is made to avoid issues with caching the data. There is a blog post within the link above somehwere that describes this in detail but I can't remember where that is at. Hope that gets you started in the right direction

Did you find this page helpful?