Introduction
@bunbase/react-sdk wraps the TypeScript SDK with React-idiomatic hooks: stale-while-revalidate caching, automatic background refetching, smart realtime cache writes, and zero extra dependencies beyond React itself.
Installation
Section titled “Installation”bun install @bunbase/js @bunbase/react-sdk -Enpm install @bunbase/js @bunbase/react-sdk -Epnpm install @bunbase/js @bunbase/react-sdk -Eyarn add @bunbase/js @bunbase/react-sdk -E@bunbase/js is a peer dependency — install both.
Wrap your app with BunBaseProvider. Pass a BunBaseClient instance:
import { BunBaseClient } from "@bunbase/js";import { BunBaseProvider } from "@bunbase/react-sdk";
const client = new BunBaseClient({ url: import.meta.env.VITE_BUNBASE_URL ?? "http://localhost:8080",});
// Restore persisted session on app loadconst at = localStorage.getItem("bb_at");const rt = localStorage.getItem("bb_rt");if (at && rt) client.auth.restoreSession(at, rt);
client.auth.onAuthChange((session) => { if (session) { localStorage.setItem("bb_at", session.accessToken); localStorage.setItem("bb_rt", session.refreshToken); } else { localStorage.removeItem("bb_at"); localStorage.removeItem("bb_rt"); }});
ReactDOM.createRoot(document.getElementById("root")!).render( <BunBaseProvider client={client}> <App /> </BunBaseProvider>);BunBaseProvider initialises the query cache and wires window focus refetching — stale entries are silently revalidated whenever the user returns to the tab.
Persistent cache storage
Section titled “Persistent cache storage”By default the cache is in-memory and resets on page reload. Pass a cacheStorage adapter to persist it — hooks will show data instantly on the next visit with no loading state.
Web (localStorage)
Section titled “Web (localStorage)”import { localStorageAdapter } from "@bunbase/react-sdk";
<BunBaseProvider client={client} cacheStorage={localStorageAdapter}>React Native (AsyncStorage)
Section titled “React Native (AsyncStorage)”import AsyncStorage from "@react-native-async-storage/async-storage";
const asyncStorageAdapter = { getItem: (key) => AsyncStorage.getItem(key), setItem: (key, value) => AsyncStorage.setItem(key, value), removeItem: (key) => AsyncStorage.removeItem(key), getAllKeys: async () => { const keys = await AsyncStorage.getAllKeys(); return [...keys]; },};
<BunBaseProvider client={client} cacheStorage={asyncStorageAdapter}>Loading state during hydration
Section titled “Loading state during hydration”When a storage adapter is provided, BunBaseProvider awaits hydration before rendering children. Use the fallback prop to show a splash screen during that window:
<BunBaseProvider client={client} cacheStorage={asyncStorageAdapter} fallback={<SplashScreen />}> <App /></BunBaseProvider>On a warm start the hydration is near-instant. On first install the cache is empty and children render immediately.
Custom namespace
Section titled “Custom namespace”If multiple BunBase apps share the same storage, set storagePrefix to avoid key collisions:
<BunBaseProvider client={client} cacheStorage={localStorageAdapter} storagePrefix="myapp:cache:">Cache lifetime and logout
Section titled “Cache lifetime and logout”How long does persistent data last?
Section titled “How long does persistent data last?”Entries written to storage have no hard expiry — they stay until explicitly cleared or the user clears their storage. Each entry stores a staleAt timestamp: on the next visit the data is shown immediately (even if stale) and a background refetch runs to freshen it. Stale data is never blank — it’s always shown while the network request is in flight.
This means public data (horse listings, categories, etc.) survives app restarts indefinitely. That is usually what you want for data that doesn’t change per-user.
Clearing cache on logout
Section titled “Clearing cache on logout”By default nothing is cleared when a user logs out. Use clearCacheOnLogout to control this:
// Clear the entire cache on logout (full reset)<BunBaseProvider client={client} cacheStorage={localStorageAdapter} clearCacheOnLogout>// Clear only user-specific collections — keep public data cached<BunBaseProvider client={client} cacheStorage={localStorageAdapter} clearCacheOnLogout={["collection:orders", "collection:my-horses"]}>The prefixes match against cache keys which follow the pattern {collection}:{list|get}:..., so "collection:orders" clears all list and record entries for the orders collection.
Manual clear
Section titled “Manual clear”You can also clear the cache imperatively at any time via the cache object from useBunBase():
const { cache } = useBunBase();
// Clear everythingcache.clear();
// Clear one collectioncache.clear("collection:orders");How the cache works
Section titled “How the cache works”Every hook reads from and writes to a shared in-memory QueryCache. Keys follow the pattern:
| Key | Written by |
|---|---|
{collection}:list:{query} | useList |
{collection}:get:{id} | useRecord, useList (pre-population), realtime events |
Stale-while-revalidate: on first render the hook shows cached data immediately (even if stale) and triggers a background refetch. When the fresh data arrives, the component re-renders — but only if the data actually changed (shallow equality check).
Pre-population: after useList resolves, each record is written into its own get key. Navigating to a detail page with useRecord will show the data instantly with no loading state.