Dynamically prefix all queryKeys
We have a setup whereby our APIs return different data, based on which
account_id
the JWT is issued for. E.g. posts.list
returns posts only for the authorised account_id
without having to specify any filters, etc.
Is there a good way to dynamically transform all query keys and prefix them with the account_id
, so that we wouldn't have to manually update all queries to do so, and avoid us missing to add it, in which case we can accidentally display stale data from a previously loaded account. I know we could flush the cache every time the account_id
changes, but would much prefer to keep the caching in place.10 Replies
jolly-crimson•2y ago
I‘d be concerned if the cache persists between user logout / login
firm-tanOP•2y ago
it doesn't, we purge the cache on logout
jolly-crimson•2y ago
But nonetheless: this is a pattern that could help you:
https://tkdodo.eu/blog/the-query-options-api#query-factories
The Query Options API
v5 brought a new, powerful API, especially if you're using React Query with TypeScript...
firm-tanOP•2y ago
Found a related question on github: https://github.com/TanStack/query/discussions/3743
We want to avoid just that – having to pass around accountIds, and manually prefixing them to frontend/backend functionality. By limiting the surface area of account_id's, we can have a much more easily testable and secure system. Manual prefixing is much more prone to errors and demands for individual tests on a much wider surface area.
GitHub
Global scope for react query keys? · TanStack query · Discussion #3...
In most apps there is the need to scope cached queries by default. Let's say you allow users to use multiple accounts. You'd probably want to scope each and every query to the account the u...
firm-tanOP•2y ago
I think both of these options are too error-prone. Easy to forget passing in accountId, and difficult to globally type queryKeys to start with an accountId.
jolly-crimson•2y ago
Did you read the link I posted?
firm-tanOP•2y ago
I did, and I like the pattern. But I'm not sure it addresses my original question about scoping. I guess I could make a function that outputs a factory, but then again we also use e.g. trpc alongside other queries, which makes things a bit more complicated.
jolly-crimson•2y ago
Just put the accountId in the first
all
queryKey?!
I don’t know about trpc thoughfirm-tanOP•2y ago
It's an option, but far from a global guarantee that all implementations are scoped to the current account. Would rather flush the cache on an account change vs. this, still.
If I think about e.g. server-side caching with Redis or other means, I would always namespace on the cache client level, rather than individual implementations. The surface area for testing for account isolation would be
1
instead of n of keys
.
Found a potential solution – defining a custom queryKeyHashFn. Alternatively, initiating a new instance of queryClient per account, and persisting them under different keys.
Works perfectly well. Persisting, and everything. TRPC + regular useQuery calls both with one go.jolly-crimson•2y ago
Nice solution!!