T
TanStack3y ago
optimistic-gold

How to run useQuery with watch

I am receiving error "Error: vue-query hooks can only be used inside setup() function."
15 Replies
genetic-orange
genetic-orange3y ago
Hi. You can't use useQuery, useQueries, useEtc outside of setup function. To use query in watch define queryClient, and then in watch trigger queryClient.fetchQuery(key,fn,options)
optimistic-gold
optimistic-goldOP3y ago
thanks! !solved Should my entire app reuse a single queryClient? The docs explain how to use the different methods but is there a good resource for adding a queryClient to a vue app?
rival-black
rival-black3y ago
Yes, your app should use a single QueryClient. Ideally via VueQueryPlugin.
optimistic-gold
optimistic-goldOP3y ago
@MrMentor If via VueQueryPlugin will I still be able to use queryClient.fetchQuery in a watch as Max described above? I cant find any info about getting a queryClient object from VueQueryPlugin
rival-black
rival-black3y ago
My first question would be - why do you need to run useQuery in watch. Cause it seems to be a problem in the first place (you should avoid it). If you have a really good reason for that, you can use useQueryClient composable in setup and then use it in watch
optimistic-gold
optimistic-goldOP3y ago
I appreciate your holistic approach. So Im building a search bar with filters and the data needs to be queried again when a filter changes
rival-black
rival-black3y ago
So in Vue you have reactive values which could be observed automatically without any additional code required from developer. I would see it something like:
const filters = reactive({
filter1: 'a',
filter2: 'b',
})

const query = useQuery(['query', filters], () => yourFetchFunction(filters))

const onFiltersChange = (newFilters) => {
// update your filters here, but DO NOT OVERWRITE WHOLE OBJECT!
// ex. iterate over keys to update it, etc...
}
const filters = reactive({
filter1: 'a',
filter2: 'b',
})

const query = useQuery(['query', filters], () => yourFetchFunction(filters))

const onFiltersChange = (newFilters) => {
// update your filters here, but DO NOT OVERWRITE WHOLE OBJECT!
// ex. iterate over keys to update it, etc...
}
This will make your query to be updated automatically and fetch new data whenever filters change.
optimistic-gold
optimistic-goldOP3y ago
Thats amazing thanks for explaining that. I didnt realize vue query worked in that way Currently I am calling useQuery in a service.ts that exports a getData function. Is this a sensible design? Currently I am parsing my filters into an object that is a querykey. Would it be best to pass the filters in raw and then manage them inside the queryFn and select function?
rival-black
rival-black3y ago
That depends on what is your use-case. Generally useQuery should be called inside setup of the component. You can extract it to some other composable to reuse it across components, but nevertheless it should be called inside setup. As for queryKey - it's your identifier of the query, and it should contain all parameters that you need to make a proper API call. Whether that will be array of primitives or objects... It does not really matter. See https://tanstack.com/query/v4/docs/guides/query-keys What should be noticed though, is that you can pass those parameters to queryFn directly or use the function context to access it, after they have been unwrapped. See https://tanstack.com/query/v4/docs/guides/query-functions#queryfunctioncontext and https://tanstack.com/query/v4/docs/guides/query-functions#query-function-variables
optimistic-gold
optimistic-goldOP3y ago
so I am calling it inside setup currently. my question is if the queryFN parameters are modified after they are passed to the composable but before they are passed to usequery, since they are reactive will everything still update automatically?
rival-black
rival-black3y ago
queryFn is called every time fetch needs to happen. So if you pass some reactive properties to that function, they should always have fresh values.
optimistic-gold
optimistic-goldOP3y ago
if the reactive value is only used in the select function and it changes, will that update as well?
rival-black
rival-black3y ago
if it's used only in select then no, cause select is run after fetch happend. if you provide that reactive prop to queryKey as well it will work.
optimistic-gold
optimistic-goldOP3y ago
ah i see that makes sense. thanks this does seem inefficient though because what if I just need to run the select function but I dont want to request data from the backend again? Would that be best to do that sort of filtering outside of vue query?
rival-black
rival-black3y ago
Yes, if you want to mutate data that you received from the server on demand, you should probably do that in computed outside of vue-query

Did you find this page helpful?