The React layer is exported from a separate entry point to keep the core SDK tree-shakeable:
TypeScriptimport { KeysetProvider, useContent, useKeysetBoolean } from "keysetapp/react";
KeysetProviderWrap your application (or the subtree that needs remote config) with KeysetProvider. It creates a single Keyset client and makes it available to all child components via React context.
TypeScript JSXimport { KeysetProvider } from "keysetapp/react"; const keysetConfig = { apiKey: "pkey_your_public_key", cacheTTL: 60000, cache: { enabled: true, ttl: 60000 }, }; export default function App() { return ( <KeysetProvider config={keysetConfig}> <Router /> </KeysetProvider> ); }
Props
| Prop | Type | Required | Description |
|---|---|---|---|
config | KeysetConfig | Yes | Same config object accepted by new Keyset(config). See Configuration. |
children | React.ReactNode | Yes | Your component tree. |
The client is memoized and only re-created when apiKey, baseUrl, retries, or timeout change.
useKeyset()Returns the raw Keyset client instance from context. Use this when you need direct access to the client — for example, to call write methods.
TypeScript JSXimport { useKeyset } from "keysetapp/react"; function AdminPanel() { const client = useKeyset(); const handleCreate = async () => { await client.content.create({ key: "feature_x", value: true, type: "boolean" }); }; return <button onClick={handleCreate}>Enable Feature X</button>; }
Returns — Keyset client instance.
Throws — "useKeyset must be used inside Keyset Provider" if called outside KeysetProvider.
useContent(options?)Fetches all remote config entries and exposes them with loading/error state.
TypeScript JSXimport { useContent } from "keysetapp/react"; function ConfigPanel() { const { data, loading, error, refetch } = useContent(); if (loading) return <p>Loading config…</p>; if (error) return <p>Failed to load: {error}</p>; return ( <> <pre>{JSON.stringify(data, null, 2)}</pre> <button onClick={refetch}>Refresh</button> </> ); }
Options
| Option | Type | Default | Description |
|---|---|---|---|
autoFetch | boolean | true | Fetch automatically on mount. Set to false to fetch manually via refetch. |
Returns
| Property | Type | Description |
|---|---|---|
data | Record<string, unknown> | All remote config entries as a flat key-value map. {} until loaded. |
loading | boolean | true while fetching. |
error | string | null | Error message if the request failed, otherwise null. |
refetch | () => Promise<void> | Trigger a fresh fetch manually. |
Manual fetch example
TypeScript JSXconst { data, loading, refetch } = useContent({ autoFetch: false }); // Fetch on user action return <button onClick={refetch}>Load Config</button>;
useContentKey<T>(key)Returns the value of a single key from the flat content map. Internally calls useContent(), so all entries are fetched.
TypeScript JSXimport { useContentKey } from "keysetapp/react"; function HeroBanner() { const { value, loading, error } = useContentKey<string>("hero_title"); if (loading) return <p>Loading…</p>; return <h1>{value ?? "Welcome"}</h1>; }
Parameters
| Param | Type | Description |
|---|---|---|
key | string | The config key to retrieve. |
Returns
| Property | Type | Description |
|---|---|---|
value | T | undefined | The value cast to T, or undefined if the key does not exist. |
loading | boolean | true while fetching. |
error | string | null | Error message or null. |
refetch | () => Promise<void> | Re-fetch all content. |
These hooks fetch only the single key they need and return a strongly-typed value. They all follow the same { value, loading } return shape.
useKeysetString(key, defaultValue?)TypeScript JSXimport { useKeysetString } from "keysetapp/react"; function Headline() { const { value, loading } = useKeysetString("hero_title", "Welcome"); return loading ? <span>…</span> : <h1>{value}</h1>; }
| Param | Type | Default |
|---|---|---|
key | string | — |
defaultValue | string | "" |
Returns { value: string; loading: boolean }
useKeysetNumber(key, defaultValue?)TypeScript JSXconst { value: limit, loading } = useKeysetNumber("max_results", 10);
| Param | Type | Default |
|---|---|---|
key | string | — |
defaultValue | number | 0 |
Returns { value: number; loading: boolean }
useKeysetBoolean(key, defaultValue?)Ideal for feature flags.
TypeScript JSXimport { useKeysetBoolean } from "keysetapp/react"; function NewDashboard() { const { value: isEnabled, loading } = useKeysetBoolean("new_dashboard", false); if (loading || !isEnabled) return <OldDashboard />; return <NewDashboardComponent />; }
| Param | Type | Default |
|---|---|---|
key | string | — |
defaultValue | boolean | false |
Returns { value: boolean; loading: boolean }
useKeysetJSON<T>(key, defaultValue?)Returns a parsed, fully-typed JSON value.
TypeScript JSXinterface NavLink { label: string; href: string } const { value: links } = useKeysetJSON<NavLink[]>("nav_links", []);
| Param | Type | Default |
|---|---|---|
key | string | — |
defaultValue | T | null | null |
Returns { value: T | null; loading: boolean }
useKeysetURL(key, defaultValue?)Returns a URL string entry (type must be "url").
TypeScript JSXconst { value: docsUrl } = useKeysetURL("docs_link", "https://docs.example.com");
| Param | Type | Default |
|---|---|---|
key | string | — |
defaultValue | string | "" |
Returns { value: string; loading: boolean }
useKeysetImage(key, defaultValue?)Returns an image URL string entry (type must be "image").
TypeScript JSXconst { value: logoUrl } = useKeysetImage("logo", "/logo.png"); return <img src={logoUrl} alt="Logo" />;
| Param | Type | Default |
|---|---|---|
key | string | — |
defaultValue | string | "" |
Returns { value: string; loading: boolean }
| Scenario | Hook |
|---|---|
| Feature flag (on/off) | useKeysetBoolean |
| Text / copy | useKeysetString |
| Numeric config value | useKeysetNumber |
| Complex object / array | useKeysetJSON<T> |
| External link | useKeysetURL |
| Logo / banner image | useKeysetImage |
| Untyped access to any key | useContentKey<T> |
| Access to all keys at once | useContent |
| Direct client access | useKeyset |