Skip to main content

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>
PropTypeRequiredDescription
apiKeystringYesYour environment API key
configToggleTownConfigNoSDK configuration (apiUrl, pollingInterval, onError)
contextEvaluationContextNoDefault 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>:

FieldTypeDescription
valueTThe evaluated flag value (or default if not ready)
isLoadingbooleantrue while the SDK is initializing
isReadybooleantrue once the SDK has fetched flags
errorError | nullInitialization 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 /* ... */;
}
ReturnTypeDescription
clientToggleTownClient | nullThe underlying SDK client
isReadybooleanWhether the SDK is initialized
isLoadingbooleanWhether the SDK is initializing
errorError | nullInitialization error
contextEvaluationContextCurrent evaluation context
setContext(ctx) => voidReplace the entire context
updateContext(updates) => voidMerge 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';