Cache & Invalidation
Elur Query maintains a global in-memory cache shared by all createQuery
instances. You can read, write, and invalidate cache entries imperatively
without creating a query.
# Cache helpers
import {
getQueryData, setQueryData, updateQueryData,
invalidateQueries, clearQueryCache, setQueryCacheTime,
} from "@elurjs/query";# getQueryData<T>(key, options?)
Reads cached data without creating a query. Returns T | undefined:
const users = getQueryData<User[]>("users/list");
const user = getQueryData<User>("users", { params: { id: "abc" } });# setQueryData<T>(key, data, options?)
Writes data directly into cache and updates active query signals. Returns
void. Active queries with the same key immediately receive the new data
via sync notification (status → "success", data → new value):
setQueryData("users/list", [...users, { id: 3, name: "Mia" }]);
setQueryData("users", userData, { params: { id: "abc" } });# updateQueryData<T>(key, updater, options?)
Atomic cache update from previous value. Returns the new value:
const next = updateQueryData("users/list", (current = []) =>
current.map((u) => u.id === 3 ? { ...u, name: "Mia V2" } : u)
);
console.log(next); // the updated array# invalidateQueries(key)
Forces all active createQuery instances with the given key to refetch.
Clears cached data and in-flight requests so subscribers start a fresh
fetch instead of sharing a stale promise that was started before the
invalidation.
When queries use params, invalidating the base key also invalidates every
param variant:
invalidateQueries("posts");
// Clears: "posts", "posts::{"page":1}", "posts::{"page":2}", etc.# clearQueryCache(key?)
Clears cache entries and in-flight requests. Without argument, clears everything and stops the GC timer:
clearQueryCache(); // clear all + stop GC
clearQueryCache("posts"); // clear "posts" and all param variants# setQueryCacheTime(ms)
Sets how long cache entries with zero subscribers are kept alive (default: 5 minutes):
setQueryCacheTime(10 * 60 * 1000); // 10 minutes
setQueryCacheTime(Infinity); // keep forever# QueryCacheOptions
Used by getQueryData, setQueryData, updateQueryData:
| Field | Type | Description |
|---|---|---|
params |
unknown |
Params value to build effective key |
serializeParams |
(params: unknown) => string |
Custom serializer (must match query's) |
# clearQueryCache vs invalidateQueries
These two helpers look similar but behave differently:
| Behavior | invalidateQueries(key) |
clearQueryCache(key) |
|---|---|---|
| Clears cache entries | Yes | Yes |
| Clears in-flight requests | Yes | Yes |
| Triggers refetch on active queries | Yes | No |
| Notifies active queries | Yes (via sync + run) | Yes (via sync only) |
invalidateQueries is the right choice after a mutation — it clears the
cache and forces active queries to refetch immediately.
clearQueryCache is for teardown or testing — it clears the cache and
notifies active queries that their data is gone (status → pending, data →
undefined/placeholder), but does not trigger a refetch. Active queries
will only refetch on next mount or explicit refetch().
# Invalidation flow
const createPost = createCommand(
"posts/create",
async (data) => {
const res = await fetch("/api/posts", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify(data),
});
if (!res.ok) throw new Error("Failed");
return res.json();
},
{
invalidate: ["posts/list", "feed", "stats"],
onSuccess: (data) => {
console.log("Created post:", data.id);
},
}
);
// After createPost succeeds, all active queries with keys
// "posts/list", "feed", and "stats" are refetched automatically.# GC behavior
Cache entries with zero subscribers are garbage-collected after
setQueryCacheTime ms (default 5 minutes). The GC timer runs every 60
seconds and stops when the cache is empty.
This means:
- If a component unmounts and remounts within the GC window, cached data is still available.
- If no component uses a query key for longer than the cache time, the entry is evicted.
- Setting
setQueryCacheTime(Infinity)disables GC entirely.