A polling refresh cannot use useFetch or useQuery, because refetch() always sets loading, and a spinner bound to it flashes on every poll. There is no first-load / background-refresh distinction.
Where it bites
A listening view polls every 60 seconds and deliberately keeps the loading state out of it:
const loadData = async ({ quiet = false } = {}) => {
if (!quiet) loading.set(true)
...
}
onMount(() => {
void loadData()
setInterval(() => void loadData({ quiet: true }), 60_000)
})That is the one thing the hand-rolled version does that the composable cannot express, and it is why this view is the only one in the app that could not move onto useFetch. Converting it would put a spinner on screen once a minute, forever.
Cause
fetchData opens with an unconditional loading.set(true) in both primitives — signals.ts:1140 for useFetch, signals.ts:1552 for useQuery — and neither takes a background / quiet / silent option. Grepping the whole of useFetch for any of those names, or for isFetching, returns nothing.
useQuery almost has the answer, but it is not reachable
useQuery tracks isStale and returns it (signals.ts:1634):
return {
data: data,
loading: loading,
error: error,
isStale: isStale,
refetch: fetchData,
invalidate: ...
}but StxQueryResult in dist/stx.d.ts declares only:
interface StxQueryResult<T> {
data: StxSignal<T | null>
loading: StxSignal<boolean>
error: StxSignal<Error | null>
refetch: () => Promise<void>
}So isStale and invalidate both exist at runtime and are invisible to the type — reading either is a type error on a value that is really there. That is the same class as #1923 and the navigate / useRoute.fullPath cases: stx.d.ts describing the registry by hand and drifting from signals.ts.
Suggested
Two separate things, and the first is the one that unblocks the app:
- A
background: true(or{ silent: true }) option onrefetch, so a poll updatesdatawithout touchingloading. The convention elsewhere is a second flag —loadingfor the first load,isFetchingfor any in-flight request — which would also let a view show a subtle indicator during a poll rather than nothing at all. - Add
isStaleandinvalidatetoStxQueryResultsouseQuery's existing surface is usable.