-
Hi! I'm trying to work-around limitations of how queryKeys work. However, since values of queryKey get stringified - this doesn't seem to be doable. Lets imagine such example: class MyFancyService {
constructor (locale, secret, fetcher) {
this.locale = locale
this.secret = secret
this.fetcher = fetcher
}
action = () => {
return new Promise((resolve, reject) => resolve(`${this.locale}-${this.secret}`))
}
}
const useMyFancyService = () => {
// contextual data
const { locale } = useLocaleStore()
const { locale } = useSecretStore()
const fetcher = (...props) => { return fetch(props)}
return useMemo(() => new MyFancyService(locale, secret, fetcher), [locale, secret, fetcher])
} And then using such service within reactQuery usually tends to look like this: const useMyFancyQuery = () => {
const myFancyService = useMyFancyService()
return useQuery({
queryKey: ['fancy-key'],
queryFn: () => myFancyService.action(),
})
} Now the problem here is that I would like In this example, whenever fetcher dependency changes within useMyFancyService, we will re-create it. However, from stringification standpoint, we will yield with same stringified value as before. Since, functions gets ommited from stringification. What if we were to introduce new referential based property for useQuery? in that case we could: const useMyFancyQuery = () => {
const myFancyService = useMyFancyService()
return useQuery({
queryKey: ['fancy-key'],
queryFn: () => myFancyService.action(),
queryReferentialDependencies: [myFancyService]
})
}
Current thoughts/solutions:
I haven't seen any issues/suggestions regarding this, so I'm really curious on your take regarding this. |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 12 replies
-
From my limited testing, providing a service-class directly (eg. I probably would've tried to use eg.
So here's an alternative idea, this might be horrible - but here goes: const useReferentialQueryKey = (queryKey, deps) => {
const [updateCount, setUpdateCount] = React.useState(0)
React.useEffect(() => {
setUpdateCount(cnt => cnt+1)
}, deps)
return queryKey.concat({ ref: updateCount })
}
const useMyFancyQuery = () => {
const myFancyService = useMyFancyService()
const serviceKey = useReferentialQueryKey(['fancy-service'], [myFancyService])
return useQuery({
queryKey: serviceKey
queryFn: () => myFancyService.action(),
})
} |
Beta Was this translation helpful? Give feedback.
-
keys need to be hashed so that we can persist them, which is important for a lot of things like server-side-rendering & hydration as well as persistence to external storages. You can pass your own |
Beta Was this translation helpful? Give feedback.
This is a valid argument. However I would just use
queryKeyHashFn
, and define your dependencies, like TkDodo says as well.However, if you really don't want to do this, I guess you could try to use the same idea as above with
queryKeyHashFn
. It does seem a bit hacky though. But it would mean you don't pollute your keys directly - just the hash. But you need different hashes if the reference change...