React SDK
React hooks and context provider for ToggleTown. Built on top of the JavaScript SDK.
Package: @toggletown/sdk-react
Installation
npm install @toggletown/sdk-react
Quick Start
Wrap your app with ToggleTownProvider, then use hooks in any component:
import { ToggleTownProvider, useBooleanFlag } from '@toggletown/sdk-react';
function App() {
return (
<ToggleTownProvider
apiKey="tt_live_your_api_key"
context={{ userId: 'user-123', plan: 'pro' }}
>
<MyComponent />
</ToggleTownProvider>
);
}
function MyComponent() {
const { value: showNewFeature, isLoading } = useBooleanFlag('new-feature', false);
if (isLoading) return <div>Loading...</div>;
return showNewFeature ? <NewFeature /> : <OldFeature />;
}
Provider
The ToggleTownProvider initializes the SDK and makes it available to all child components.
<ToggleTownProvider
apiKey="tt_live_your_api_key"
config={{
apiUrl: 'https://api.toggletown.com',
pollingInterval: 30000,
onError: (error) => console.error(error),
}}
context={{
userId: currentUser.id,
plan: currentUser.plan,
}}
>
{children}
</ToggleTownProvider>
| Prop | Type | Required | Description |
|---|---|---|---|
apiKey | string | Yes | Your environment API key |
config | ToggleTownConfig | No | SDK configuration (apiUrl, pollingInterval, onError) |
context | EvaluationContext | No | Default user context for flag evaluation |
The provider handles initialization, cleanup, and error states automatically.
Hooks
useBooleanFlag
const { value, isLoading, isReady, error } = useBooleanFlag('flag-key', false);
useStringFlag
const { value, isLoading, isReady, error } = useStringFlag('theme', 'light');
useNumberFlag
const { value, isLoading, isReady, error } = useNumberFlag('max-items', 10);
useJSONFlag
const { value, isLoading, isReady, error } = useJSONFlag('config', { enabled: false });
useFlag
Alias for useBooleanFlag:
const { value, isLoading } = useFlag('feature-enabled', false);
Hook Return Type
All flag hooks return a FlagResult<T>:
| Field | Type | Description |
|---|---|---|
value | T | The evaluated flag value (or default if not ready) |
isLoading | boolean | true while the SDK is initializing |
isReady | boolean | true once the SDK has fetched flags |
error | Error | null | Initialization error, if any |
Context Override
All flag hooks accept an optional context override as the third argument:
const { value } = useBooleanFlag('feature', false, {
userId: 'specific-user',
plan: 'enterprise',
});
This overrides the context set on the provider for this specific flag evaluation.
useToggleTown
Access the SDK client and context management functions:
import { useToggleTown } from '@toggletown/sdk-react';
function UserProfile() {
const { client, isReady, isLoading, error, context, setContext, updateContext } = useToggleTown();
const onLogin = (user) => {
// Update context when user logs in
updateContext({ userId: user.id, plan: user.plan });
};
const onLogout = () => {
// Reset context
setContext({});
};
return /* ... */;
}
| Return | Type | Description |
|---|---|---|
client | ToggleTownClient | null | The underlying SDK client |
isReady | boolean | Whether the SDK is initialized |
isLoading | boolean | Whether the SDK is initializing |
error | Error | null | Initialization error |
context | EvaluationContext | Current evaluation context |
setContext | (ctx) => void | Replace the entire context |
updateContext | (updates) => void | Merge updates into the context |
useAllFlags
Get all flags for debugging:
import { useAllFlags } from '@toggletown/sdk-react';
function DebugPanel() {
const { flags, isLoading, isReady, error } = useAllFlags();
return (
<pre>{JSON.stringify(flags, null, 2)}</pre>
);
}
Updating Context
Update the user context when authentication state changes:
function AuthWrapper({ children }) {
const { updateContext, setContext } = useToggleTown();
const { user, isLoggedIn } = useAuth();
useEffect(() => {
if (isLoggedIn && user) {
updateContext({ userId: user.id, plan: user.plan, email: user.email });
} else {
setContext({});
}
}, [isLoggedIn, user]);
return children;
}
Loading States
Handle the loading state while the SDK initializes:
function FeatureGate({ flagKey, children, fallback = null }) {
const { value: enabled, isLoading } = useBooleanFlag(flagKey, false);
if (isLoading) return <LoadingSpinner />;
return enabled ? children : fallback;
}
// Usage
<FeatureGate flagKey="new-dashboard">
<NewDashboard />
</FeatureGate>
Error Handling
Handle initialization errors gracefully:
function App() {
return (
<ToggleTownProvider
apiKey="tt_live_xxx"
config={{
onError: (error) => Sentry.captureException(error),
}}
>
<FlagConsumer />
</ToggleTownProvider>
);
}
function FlagConsumer() {
const { error, isLoading } = useToggleTown();
if (error) {
// SDK failed to initialize — flags will use defaults
console.warn('Flags unavailable:', error.message);
}
// Components using flag hooks will get default values when SDK fails
return <MyApp />;
}
TypeScript
All types are exported:
import type {
ToggleTownProviderProps,
ToggleTownContextValue,
FlagResult,
} from '@toggletown/sdk-react';
import type { EvaluationContext, FlagConfig } from '@toggletown/types';
import type { ToggleTownConfig } from '@toggletown/sdk-js';