query-key-factory
query-key-factory copied to clipboard
Nested keys required?
Hello, with React query i naturally have this scenario:
-list of customers by account filtered by order by
how i map this to cache keys is:
`function customersByAccountId(accountId: number) { return ["customerListByAccountId", accountId]; }
function customersByAccountIdFiltered(accountId: number, queryFilter: QueryFilter) { return [...customersByAccountId(accountId), "list", { queryFilter }]; }`
This way, when i edit an attribute for a customer, i can: update the in memory query for customersByAccountIdFiltered (which will change the attribute on the current screen, without reload)
and invalidate customersByAccountId (with refetchActive: false,) which will invalidate all other cached filtered entries.
How do i map this with query-key-factory?
@kimbuba can you share a little more context about your use case? especially about:
invalidate customersByAccountId (with refetchActive: false,) which will invalidate all other cached filtered entries.
I can see ["customerListByAccountId", accountId, 'list']
being enough to invalidate the "other cached filtered entries", so I want to understand a little more about how you use ["customerListByAccountId", accountId]
connected to the ["customerListByAccountId", accountId, 'list']
queries, so that I can give you a proper solution or really understand if that's a use-case that the lib does not support yet
Hello Luke! Yes sure. I need to support the following keys structure
["customerListByAccountId", accountId, 'list', {orderBy:"create_date"}] ["customerListByAccountId", accountId, 'list', {orderBy:"id"}] ["customerListByAccountId", accountId, 'list2', {orderBy:"create_date"}]
how do i clean this using your library? accountId is a variable number. Basically i need to do the following, clean: ["customerListByAccountId", accountId]
how do you translate it with createQueryKeyStore?
What's the difference between list
and list2
? Is that also a dynamic parameter? Maybe pagination?
I'm asking because it really seems to me that this structure should fit your needs:
const store = createQueryKeyStore({
customers: {
listByAccountId: (accountId: number, queryFilter: QueryFilter) => [accountId, 'list', queryFilter],
// ['customers', 'listByAccountId', accountId, 'list', queryFilter]
},
});
// then on your components
useQuery(store.customers.listByAccountId(accountId, queryFilter));
queryClient.invalidateQueries(store.customers.listByAccountId(accountId, {}), { refetchActive: false });
// to understand why invalidating ['customers', 'listByAccountId', accountId, 'list', {}] works
// see this example: https://codesandbox.io/s/react-query-object-keys-pogsr
// or if you prefer:
queryClient.invalidateQueries([...store.customers.listByAccountId._def, accountId], { refetchActive: false });
// ^? ['customers', 'listByAccountId', accountId]
queryClient.invalidateQueries(Array.prototype.concat(store.customers.listByAccountId._def, accountId), { refetchActive: false });
// ^? ['customers', 'listByAccountId', accountId]
thanks, i see.
Would it be possible to go more deeper in the hierarchy?
Say: customer/10/stakeholders/213/load that would easily translate into [customer,10,stakeholders,213,load] so i could easily invalidate customerId 10 and everything under it with this key [customer,10]
@kimbuba oh, that's definitely a use case not supported yet. Do you have more examples of similar use cases?
that would be to support a hierarchy structure. But i'm trying to adapt my current structure to your library.
Btw is this
queryClient.invalidateQueries([...store.customers.accountId._def, accountId], { refetchActive: false });
actually
queryClient.invalidateQueries([...store.customers. listByAccountId._def, accountId], { refetchActive: false });
or am i missing something?
that would be to support a hierarchy structure.
Basically scoping some keys to an entity ID, or any other use cases? I remember thinking something like this when designing this first api but couldn't think about any examples at the time. So, as much information for use cases like these as I can get will help me think about how to support it
Btw is this
queryClient.invalidateQueries([...store.customers.accountId._def, accountId], { refetchActive: false });
actually
queryClient.invalidateQueries([...store.customers. listByAccountId._def, accountId], { refetchActive: false });
Yes you're correct, I totally miswrote that 😓
np,
here is another example: I have a list of accounts and each account has customers i want to do different lists per customers, as they are calling different endpoints. I could put everything as in a filter for this simple example but i may not want to.
API:
- customersListByAccountInvited(1, "desc");
- customersListByAccountNotInvited(2, "asc");
The first gives the list of all customers non invited ordered by desc. The second gives the list of all customers non invited ordered by asc.
This would naturally map as: ["customers",1,"invited", {sort:"desc"}]
And: ["customers",1,"non_invited", {sort:"asc"}]
With 1
, the accountId
Now say i'm adding a customer to the first cache.
I would setQuery
on["customers",1,"invited", {sort:"desc"}]
and add a user "John"
I now need to invalidate the following
queryClient.invalidateQueries(["customers",1], { refetchActive: false });
This way:
- The current list has updated data without refetching
- The second list is invalidated and will be reloaded
Is there a way to map this?
Something like this would not give me what i want to accomplish:
customers: {
listInvited: (accountId: number, sort: {"asc"|"desc"}) => [accountId, { sort }],
listNonInvited: (accountId: number, sort: {"asc"|"desc"}) => [accountId, { sort }],
},
As there would be no way to invalidate
queryClient.invalidateQueries(["customers",1], { refetchActive: false });
Thanks for the information @kimbuba, I'll start some exploration towards that use case
@kimbuba just letting you know, v1.0 has been released with support for nested keys: https://github.com/lukemorales/query-key-factory/releases/tag/v1.0.0