Cache
SWRV uses a provider-scoped cache model. Each client owns its cache, listeners, dedupe records, and preload records.
WARNING
In most cases, you should not write to the cache directly. Prefer mutate, useSWRVMutation, preload, or config-level fallback so loading and listener behavior stays consistent.
Cache provider
A cache provider is a Map-like object:
interface Cache<Data> {
get(key: string): Data | undefined;
set(key: string, value: Data): void;
delete(key: string): void;
keys(): IterableIterator<string>;
}Create cache provider
Use provider, cache, or client on SWRVConfig to define cache ownership:
<script setup lang="ts">
import { SWRVConfig } from "swrv";
const value = {
provider: () => new Map(),
};
</script>
<template>
<SWRVConfig :value="value">
<Page />
</SWRVConfig>
</template>All SWRV composable calls under that boundary use the same provider.
When boundaries are nested, composable calls use the nearest upper-level provider. If there is no custom provider above them, they fall back to the default root cache.
WARNING
When the boundary is remounted, the provider is recreated too. Keep custom providers high enough in the app tree, or create them outside component setup, if the cache should survive remounts.
Access current cache provider
Inside setup, use useSWRVConfig() to access the active scoped helpers:
const { cache, mutate } = useSWRVConfig();If a custom provider is in use, this keeps you aligned with the current boundary.
WARNING
If you use a custom cache boundary, the root global mutate helper is no longer the right tool for components inside that boundary. Use useSWRVConfig().mutate so the mutation targets the current provider.
Experimental: extend cache provider
When multiple SWRVConfig boundaries are nested, provider receives the parent cache:
const value = {
provider: (parentCache: Map<string, unknown>) => parentCache,
};This makes it possible to wrap or extend the parent cache instead of replacing it outright.
Examples
LocalStorage based persistent cache
function localStorageProvider() {
const map = new Map<string, unknown>(JSON.parse(localStorage.getItem("app-cache") ?? "[]"));
window.addEventListener("beforeunload", () => {
localStorage.setItem("app-cache", JSON.stringify(Array.from(map.entries())));
});
return map;
}Then use it through SWRVConfig:
<SWRVConfig :value="{ provider: localStorageProvider }">
<App />
</SWRVConfig>As an improvement, you can also keep an in-memory cache as a buffer and write back to localStorage periodically. The same layered pattern can be adapted to IndexedDB or other custom storages.
Reset cache between test cases
In tests, create a fresh provider or client per test instead of sharing one global cache:
<SWRVConfig :value="{ provider: () => new Map() }">
<App />
</SWRVConfig>Or create a request-scoped client explicitly:
import { createSWRVClient } from "swrv";
const client = createSWRVClient();Then provide that client through SWRVConfig for the test render.
Modify the cache data
When you need to change cached data, prefer mutate:
const { mutate } = useSWRVConfig();
await mutate("/api/user", (current) => (current ? { ...current, name: "Grace" } : current));You can also clear multiple keys through a filter:
const { mutate } = useSWRVConfig();
await mutate((key) => true, undefined, {
revalidate: false,
});That updates the cache while preserving SWRV’s normal mutation and listener semantics. See also Mutation and Arguments.
