Skip to content

Hooks

All hooks are imported from @kinbot/react:

import { useKinBot, useStorage, useTheme, ... } from "@kinbot/react";

The primary hook. Provides the full SDK instance with reactive theme and app updates.

const { kinbot, app, theme, ready } = useKinBot();
PropertyTypeDescription
kinbotKinBotThe full SDK instance (access .api, .storage, .locale, etc.)
appKinBotAppMeta | nullReactive app metadata (id, name, slug, kinId, locale, user)
theme{ mode, palette }Reactive theme (light/dark)
ready() => voidCall this to signal your app has finished loading

Call ready() once your app is mounted to dismiss the loading state. Access other SDK features via kinbot (e.g. kinbot.api, kinbot.storage, kinbot.locale).

Persistent key-value storage, like useState but survives page reloads and sessions.

const [value, setValue, { loading, error, remove }] = useStorage("myKey", defaultValue);
  • setValue(newValue) persists the value server-side
  • loading is true while fetching the initial value
  • error contains any storage error (or null)
  • remove() deletes the key from storage
  • Data is stored in KinBot’s server-side storage

Lighter alternative to useKinBot when you only need theme info.

const { mode, palette } = useTheme();
// mode: "light" | "dark"

Access parent Kin information.

const { kin, loading } = useKin();
// kin: { id, name, avatarUrl }

Access current user information.

const { user, loading } = useUser();
// user: { id, name, pseudonym, locale, timezone, avatarUrl }

Fetch data from the mini-app’s _server.js backend.

const { data, loading, error, refetch } = useApi("/items");

Options: { method, body, enabled }. Auto-fetches on mount and when path changes.

Fetch external data via KinBot’s HTTP proxy.

const { data, loading, error, refetch, status } = useFetch("https://api.example.com/data");

Options: { method, body, headers, json (default true), enabled (default true) }. Pass null as URL to skip fetching.

Wrap any async function with loading/error states. Great for mutations.

const { run, data, loading, error, reset } = useAsync(async (id) => {
return await api.delete(`/items/${id}`);
});
// Call manually:
await run(itemId);

Subscribe to SSE events from the backend.

// Accumulate messages:
const { messages, connected, clear } = useEventStream("update");
// Or use a callback (no accumulation):
useEventStream("update", (data) => {
console.log("Got update:", data);
});

Infinite scroll / load-more pagination.

const { items, loading, loadingMore, hasMore, loadMore, sentinelRef } = useInfiniteScroll("/items", {
pageSize: 20,
source: "api", // "api" (backend) or "http" (external)
});
return (
<div>
{items.map(item => <Item key={item.id} {...item} />)}
<div ref={sentinelRef} /> {/* auto-loads more when visible */}
</div>
);

Options: source, pageSize, pageParam, limitParam, getItems, getHasMore, autoLoad, threshold.

Traditional page-based pagination (replaces items on each page change).

const { items, loading, page, totalPages, setPage, next, prev } = usePagination("/items", {
pageSize: 10,
});

Options: source, pageSize, pageParam, limitParam, getItems, getTotal.

Search and store Kin memories from a mini-app.

const { search, store, results, loading } = useMemory();
await search("user preferences");
await store("User prefers dark mode", { category: "preference" });

Interact with the Kin’s conversation.

const { history, send, messages, loading } = useConversation();
await send("Remind me about this task");

Browser-side localStorage (not synced via KinBot). Good for UI preferences.

const [sortOrder, setSortOrder, remove] = useLocalStorage("sortOrder", "asc");

Keys are auto-prefixed with kb:. Syncs across tabs.

Form state management with validation.

const { values, errors, touched, handleChange, handleBlur, handleSubmit, reset, isValid, isDirty } =
useForm({ name: "", email: "" });

Reactive CSS media query.

const isDesktop = useMediaQuery("(min-width: 768px)");

Current responsive breakpoint.

const bp = useBreakpoint();
// "xs" (<640px) | "sm" | "md" | "lg" | "xl" (≥1280px)

Debounce a value (default 300ms).

const [search, setSearch] = useState("");
const debouncedSearch = useDebounce(search, 500);

Declarative setInterval. Pass null to pause.

useInterval(() => fetchData(), isActive ? 5000 : null);

Detect clicks outside an element.

const ref = useRef(null);
useClickOutside(ref, () => setOpen(false));

Register keyboard shortcuts. Auto-cleanup on unmount.

useShortcut("ctrl+k", () => openSearch());
useShortcut("escape", () => close());

Reactive network status.

const isOnline = useOnline();

Clipboard access with copied state feedback.

const { copy, read, copied } = useClipboard();
await copy("Hello!");
// copied is true briefly after copying
const text = await read();

Send browser notifications via the parent window.

const { notify, sending } = useNotification();
await notify("Timer Done", "Your pomodoro session is complete!");

Trigger file downloads.

const { download, downloading } = useDownload();
await download("data.json", myData); // objects auto-serialize to JSON
await download("report.csv", csvString, "text/csv");

List other mini-apps from the same Kin.

const { apps, loading, refresh } = useApps();

Listen for data shared from another app via KinBot.share().

const { data, clear } = useSharedData((payload) => {
console.log("Received from:", payload.fromName, payload.data);
});

Get the previous value from the last render.

const prevCount = usePrevious(count);

Hash-based routing for multi-page apps.

const { path, params, navigate, back } = useHashRouter("/");

See also the Router, Route, Link, and NavLink components in @kinbot/components.