Some best practices guidelines and advice with Vue
I've only recently started using this package (not sure if I should call it vue-query or react-query) but I just wanted to know best practices in terms of query keys and data...
1. Should we try to re-use queries from composables? Or should queries be more specific to the component itself?
2. When typing the keys for the query, should the query key expect multiple
Ref<>
values from the component when the query is created or should my composable return these refs to the component?
3. Is it better to use ref
or reactive
for query key values?
4. Is there a nice way to store pagination data outside of the query cached data? So that when replacing data in queries, I know everything is just a basic array of data or is there a better way of managing query structure? I haven't gotten to this yet but we use a lot of broadcasting and need to be able to replace individual values within data.26 Replies
optimistic-goldOP•3y ago
5. Can I pass reactive/ref values to a query and not have to worry about unwrapping them?
flat-fuchsia•3y ago
yoyo almost positive its impossible to pass a ref to useQuery in any form
optimistic-goldOP•3y ago
I tried this and I think it works but my UI broke for other reasons haha but starting to think that should just be in a reactive object
flat-fuchsia•3y ago
2) i'd check out this link (All About React Query (with Tanner Linsley) — Learn With Jason), but the answer is useQuery should likely be defined in a composable and reused
the useQuery function internally calls the useBaseQuery fn, the signature looks like this
arg1:
| TQueryKey
| UseQueryOptionsGeneric<TQueryFnData, TError, TData, TQueryKey>,
arg2:
| QueryFunction<TQueryFnData, UnwrapRef<TQueryKey>>
| UseQueryOptionsGeneric<TQueryFnData, TError, TData, TQueryKey> = {},
arg3: UseQueryOptionsGeneric<TQueryFnData, TError, TData, TQueryKey> = {},
so looks like can't pass ref as queryKey but could be wrong at first glance
optimistic-goldOP•3y ago
So it should always be a
reactive
, POJO, array or string etc?flat-fuchsia•3y ago
i generally just dont think it will work hahah but haven't actually tried yet
for reactive
optimistic-goldOP•3y ago
I don't see what else you would pass?
flat-fuchsia•3y ago
but primitives work for sure
optimistic-goldOP•3y ago
If you have things that are in the template like a search text-field, that's going to be
v-model
with a ref or reactive
So it would make sense to pass that to the query as the key or part of the key?flat-fuchsia•3y ago
yes, you're right but there were type issues from what I understand that prevent watch sources from being passed
optimistic-goldOP•3y ago
I'm going to test it now ha
I guess my main question was #4
How to best store pagination data so I know the structure of my query data is consistent
@mattyice78987 can confirm this works just fine
Looks like it's unwrapped somewhere
optimistic-goldOP•3y ago

stormy-gold•3y ago
All hooks in
vue-query
accept refs
reactive
or plain values
and they are unwrapped like in this function https://github.com/TanStack/query/blob/52764b0d461cbfe3acd7c0840c0477b834a9a0ac/packages/vue-query/src/useBaseQuery.ts#L104GitHub
query/useBaseQuery.ts at 52764b0d461cbfe3acd7c0840c0477b834a9a0ac ·...
🤖 Powerful asynchronous state management, server-state utilities and data fetching for TS/JS, React, Solid, Svelte and Vue. - query/useBaseQuery.ts at 52764b0d461cbfe3acd7c0840c0477b834a9a0ac · Tan...
optimistic-goldOP•3y ago
Amazing! So just type it appropriately and good to go!
flat-fuchsia•3y ago
sorry for the misdirection!
optimistic-goldOP•3y ago
It's fine. I literally started using this yesterday and it's amazing
Don't know why I haven't seen this package before
stormy-gold•3y ago
useQuery
and useInfiniteQuery
should have proper types already. There might be a problem with useMutation
and useQueries
. But this is type only problem. Functionality wise it should still work.optimistic-goldOP•3y ago
Probably just because I am using a composable I have to type my composable args
And yeah
useQuery
accepts it just fine with nothing further requiredstormy-gold•3y ago
Ad1. You can and probably should wrap your queries with your own compostables to encapsulate queryKey and queryFn, exposing only some necessary args.
For tiny apps it might be overkill, but for bigger apps it will make reuse of specific resources much easier.
optimistic-goldOP•3y ago
Yeah our app is huge...
Hence trying to make it faster
stormy-gold•3y ago
Ad2.
queryKey
is an array which can contain primitives or nested objects and arrays.
It should contain all arguments that you are passing to your queryFn
. This way by changing args you will create new cache entry. And if you will try to hit old params, results can be served from cache first.
How you will structure your queryKey is totally up to you.
You can check this page for more details: https://vue-query-next.vercel.app/#/guides/query-keysVue Query
Description
optimistic-goldOP•3y ago
The last piece for me before I go for a full in migration to this package is to work out the best way to handle paginated data and also nice, type safe
setQueriesData
so I can update multiple queries that may or may not be paginated. For example UserList
(paginated) and UserSelect
(select field, not paginated). We use a lot of broadcasting.stormy-gold•3y ago
IMHO. For paginated user list i would go with something like
['users', page]
or ['users', {page}]
.
For select field, since you have a lot of data (pagination) i would usually send denounced/throttled query to the server with user input as filter and include that in the query key, with a bit of staleTime.
This way when you type the same thing the second time, you will skip trip to the server, and could serve it from cache.
If it would not be used for some time, it will be GCed.
The only question is if you need to display something when you did not type anything, but that could be the first page of users.
I doubt anyone would scroll through thousands of users to pick one.optimistic-goldOP•3y ago
That was probably a contrived example and it's not that straightforward in our app. So I have the queries working fine
Maybe another example would be a Task List - we have a table that lists them, paginated. Then another view that only shows for a specific date range (not paginated)
So if a Task is updated somewhere else (like created and then broadcasted in), I want to update both of the above queries
One is paginated, the other is not
So for one, the Tasks are likely at
data.items
(if paginated) and the other they're just at data
(if not paginated)
But if the created/updated Tasks falls in the current week, well I want to put it in both queries without re-fetching
Not sure if I'm explaining it poorly.
Being able to update both of the above queries with type safety when using setQueriesData
is what I'm trying to do
If that helps explain my goal 🙂
I suppose the other option is to enforce API responses so that I should expect a meta
key on every response - even if not paginatedstormy-gold•3y ago
So there are two concepts you could use:
https://vue-query-next.vercel.app/#/guides/query-invalidation
https://vue-query-next.vercel.app/#/guides/optimistic-updates
From what I understand you are trying to achieve optimistic update.
I think in this case you need to figure out what works best for your data model. As every use case has it own quirks.
Vue Query
Description
optimistic-goldOP•3y ago
Yeah but updating two queries with differing structures is what I'm trying to solve
Not as simple as just applying the same updater function to both
https://github.com/TanStack/query/discussions/1780
This discussion is similar to what I want to do
I think I either have to have the same structure
Or somehow track the structure of the query
Like being able to tag if it's paginated or not