Realtime
Four hooks cover WebSocket subscriptions. All unsubscribe automatically on unmount and reconnect transparently via the underlying RealtimeClient.
useCollectionEvents
Section titled “useCollectionEvents”Subscribe to all changes in a collection.
import { useCollectionEvents } from "@bunbase/react-sdk";
function LiveFeed() { const { connected } = useCollectionEvents<Post>( "posts", (event) => { console.log(event.event, event.record); // "create" | "update" | "delete" }, { invalidateCache: true }, );
return <span>{connected ? "Live" : "Connecting…"}</span>;}useRecordEvents
Section titled “useRecordEvents”Subscribe to changes on a specific record. Pass null or undefined to skip.
import { useRecordEvents } from "@bunbase/react-sdk";
function PostDetail({ id }: { id: string }) { useRecordEvents<Post>("posts", id, (event) => { if (event.event === "delete") router.navigate("/posts"); });
// ...}useRealtime
Section titled “useRealtime”Low-level hook — subscribe to any channel by name.
import { useRealtime } from "@bunbase/react-sdk";
useRealtime("collection:posts", (event) => { ... });useRealtime("record:posts:abc123", (event) => { ... });Accepts a full SubscribeOptions object: events, filter, ids.
usePresence
Section titled “usePresence”Query which user IDs are currently present on a channel.
import { usePresence } from "@bunbase/react-sdk";
function OnlineUsers({ channel }: { channel: string }) { const { users, refresh } = usePresence(channel);
return ( <ul> {users.map((uid) => <li key={uid}>{uid}</li>)} </ul> );}invalidateCache — smart cache strategy
Section titled “invalidateCache — smart cache strategy”When invalidateCache: true is set on useCollectionEvents or useRealtime, incoming events update the cache intelligently instead of wiping everything:
| Event | Cache action |
|---|---|
update | setData(collection:get:id, record) — detail page updates instantly, zero round-trip. Lists are invalidated and re-fetch in the background. |
delete | invalidate(collection:get:id) + invalidate lists |
create | Invalidate lists only (can’t safely insert into sorted/filtered lists) |
Live list pattern
Section titled “Live list pattern”Combine useList with useCollectionEvents to keep a list in sync:
function LivePostList() { const { data, loading } = useList<Post>("posts", { sort: "-_created_at" }); useCollectionEvents("posts", undefined, { invalidateCache: true });
if (loading) return <p>Loading…</p>; return <ul>{data?.items.map((p) => <li key={p._id}>{p.title}</li>)}</ul>;}Or use the shorthand realtime: true option on useList directly — no useCollectionEvents needed:
const { data } = useList<Post>("posts", { sort: "-_created_at" }, { realtime: true });Both are equivalent. Use useCollectionEvents when you need an event callback; use realtime: true on useList when you just want cache sync.
Live detail pattern
Section titled “Live detail pattern”useRecord already subscribes to record-level events when an id is provided:
const { data: post } = useRecord<Post>("posts", id);updateevent → record written to cache, component re-renders immediately (no round-trip)deleteevent → cache cleared,databecomesundefined