query()

query() fetches data and gives you back a reactive object: loading while it is in flight, data when it arrives, error if it fails. It is available in every component - no import.

source
<script>
const posts = query('/api/posts')
</script>

{posts.loading && <p>Loading...</p>}
{posts.error && <p>Error: {posts.error.message}</p>}
{posts.data && posts.data.map(post => (
  <div>{post.title}</div>
))}

What you get back

Property Type What it is
data T | undefined The result, once it has arrived
loading boolean A fetch is in flight
error Error | undefined The fetch failed
stale boolean This should be revalidated
refetch() () => Promise Fetch again now

stale does not mean "finished". It answers "should this be revalidated", and the default staleTime is 0 - so it is true even a millisecond after a successful fetch. Use loading for spinners and data / error for branching.

Options

source
let page = 1

const items = query('/api/items', {
  params: { page, sort: 'desc' },  // page changes -> refetch
  staleTime: 30000                 // fresh for 30s
})
Option What it does
params Object appended to the URL as a query string. Reactive: change a value and the query refetches.
staleTime Milliseconds the result counts as fresh. Default 0.
cacheTime How long unused data is kept before it is dropped.
enabled Set false to hold the fetch back.
refetchOnMount Refetch stale data when a new component mounts.

Caching and names

The URL is the cache key.

Two components that call query('/api/me') share one fetch and one result, and the second one renders from cache immediately.

Pass a name in front of the URL to key the cache yourself.

You need one if a mutation is going to invalidate it:

source
<script>
// The name becomes the cache key, so a mutation can invalidate it
const posts = query('posts', '/api/posts')
</script>

When cached data exists but is stale, JAF shows it straight away and refreshes in the background.

Fetching it yourself

Pass a function instead of a URL when you need custom headers, a different body, or a non-JSON response:

source
<script>
const data = query('custom', async () => {
  const res = await fetch('/api/special', {
    headers: { 'X-Custom': 'value' }
  })
  return res.json()
})
</script>