Open quiteeasy opened 5 months ago
Interesting. This could be useful as a plugin once more stuff is exposed. I see it as a dangerous default as it would spam the server very often
Adding this as an option would be useful, but I would not set it to true
by default
If it's added, it should be fully tree shakable too
Should we add an option to QueryPlugin
or possibly another plugin (perhaps as a separate package) to enable autoRefetch
across the app, while still allowing control through each individual useQuery
options? This approach would ensure it is tree-shakable and maintains flexibility
We will see later on but probably a different kind of plugin. I think a lot of other more critical features are still missing before this 😄
Would love to see this because it enables a major use case (use useQuery
instead of adding manual polling).
This should be doable as a plugin if anybody wants to contribute to the repo. The delay plugin should help to get started
Thanks @posva! I'm writing a plugin for this but got stuck at accessing entry.stale
in the plugin. I keep getting a Cannot read properties of null (reading 'staleTime')
error. Would you have any ides or can you nudge me in the right direction? 🙏🏽
Minimal Reproduction: https://stackblitz.com/edit/github-ruyqjq?file=colada%2FautoRefetch.ts
Plugin file:
// plugins/auto-refresh/src/index.ts
import type { PiniaColadaPlugin, UseQueryEntry } from '@pinia/colada'
export interface PiniaColadaAutoRefetchOptions {
/**
* Whether to enable auto refresh by default.
* Can be overridden per query.
* @default true
*/
enabled?: boolean
}
/**
* Plugin that automatically refreshes queries when they become stale
*/
export function PiniaColadaAutoRefetch(
options: PiniaColadaAutoRefetchOptions = {},
): PiniaColadaPlugin {
// Default to enabled
const { enabled = true } = options
return ({ queryCache, scope }) => {
// Keep track of active entries and their timeouts
const refreshTimeouts = new Map<UseQueryEntry, NodeJS.Timeout>()
queryCache.$onAction(({ name, after, args }) => {
if (name === 'create') {
after((entry) => {
// Skip if auto-refresh is disabled globally or for this query
const queryEnabled = entry.options?.autoRefetch ?? enabled
if (!queryEnabled) return
scope.run(() => {
console.log('>> Running', entry.key)
watch(
() => entry.stale,
(stale) => {
console.log('>> Stale', stale)
if (stale) {
// Clear any existing timeout
const existingTimeout = refreshTimeouts.get(entry)
if (existingTimeout) {
clearTimeout(existingTimeout)
}
// Schedule a refresh
const timeout = setTimeout(() => {
if (entry.active) {
console.log('>> Refreshing stale query:', entry.key)
queryCache.fetch(entry)
}
refreshTimeouts.delete(entry)
}, 0)
refreshTimeouts.set(entry, timeout)
}
},
{ immediate: true },
)
})
})
}
// Clean up timeouts when entry is removed
if (name === 'remove') {
console.log('>> Remove', args)
const [entry] = args
const timeout = refreshTimeouts.get(entry)
if (timeout) {
clearTimeout(timeout)
refreshTimeouts.delete(entry)
}
}
})
}
}
// Add types for the new option
declare module '@pinia/colada' {
interface UseQueryOptions {
/**
* Whether to automatically refresh this query when it becomes stale.
* Requires the PiniaColadaAutoRefetch plugin.
*/
autoRefetch?: boolean
}
}
You get that error because the entry doesn't have options yet, so it cannot fetch. options
are set by useQuery()
calls. It's not a reactive property, so you can't watch it anyway. I would go for the fetch
action (among others), to add a refetch timeout
Add a boolean option,
autoRefetch
, to automatically refetch an entry when it becomes stale.