@dr-sentry/react
v1.1.4
Published
Official React SDK for the DeploySentry feature flag platform
Downloads
1,073
Maintainers
Readme
@dr-sentry/react
Official React SDK for the DeploySentry feature flag platform. Provides React hooks and a context provider for evaluating feature flags with real-time SSE updates.
Installation
npm install @dr-sentry/reactReact 18 or later is required as a peer dependency.
Quick Start
Wrap your application with DeploySentryProvider and use hooks anywhere in the tree:
import { DeploySentryProvider, useFlag } from '@dr-sentry/react';
function App() {
return (
<DeploySentryProvider
apiKey="ds_live_abc123"
baseURL="https://api.dr-sentry.com"
environment="production"
project="my-app"
application="my-web-app"
user={{ id: 'user-42' }}
>
<MyComponent />
</DeploySentryProvider>
);
}
function MyComponent() {
const showBanner = useFlag('show-banner', false);
if (!showBanner) return null;
return <div>New feature banner!</div>;
}Provider Props
| Prop | Type | Required | Description |
|---------------|--------------|----------|--------------------------------------------------|
| apiKey | string | Yes | API key for authenticating with DeploySentry. |
| baseURL | string | Yes | Base URL of the DeploySentry API. |
| environment | string | Yes | Environment identifier (e.g. "production"). |
| project | string | Yes | Project identifier. |
| application | string | Yes | Application identifier |
| user | UserContext | No | User context for targeting rules. |
| children | ReactNode | Yes | React children. |
| mode | string | No | SDK mode: server, file, or server-with-fallback. |
| flagData | object | No | Pre-loaded flag config for file/fallback mode. |
| defaults | object | No | Offline defaults consulted when the API call fails (fallback only). |
Offline / File Mode
For offline use or testing, pass pre-loaded flag config via the flagData prop:
import flagConfig from './.deploysentry/flags.json';
<DeploySentryProvider
apiKey="not-used"
baseURL=""
environment="staging"
project="my-project"
application="my-web-app"
mode="file"
flagData={flagConfig}
>
<App />
</DeploySentryProvider>Modes
| Mode | Behavior |
| --- | --- |
| server (default) | API calls + SSE streaming |
| file | Use flagData prop, evaluate locally. No server contact. |
| server-with-fallback | Try server first. If unavailable, use flagData as fallback. |
Export the config from the dashboard (App Settings → Export flags.yaml), then convert to JSON or import with a YAML plugin.
Offline Defaults (Fallback)
For resilience against transient API outages, pass a flag-export JSON via the defaults prop. Unlike flagData (which replaces the API), defaults only kicks in when the API call fails — successful live data overwrites the defaults per-key.
Generate the snapshot with the CLI:
deploysentry flags export --application web --env production -f flags.jsonThen import it as a build-time asset:
import defaults from './flags.json';
<DeploySentryProvider
apiKey={import.meta.env.VITE_DEPLOYSENTRY_API_KEY}
baseURL="https://api.dr-sentry.com"
environment="production"
project="my-app"
application="web"
defaults={defaults}
>
<App />
</DeploySentryProvider>Environment matching: the environment prop is matched against the export's environments[] first by UUID, then by name (case-insensitive). When a match is found, that env's per-flag {enabled, value} overrides the flag's global default_value. When no match, the global default_value is used (the flag is treated as enabled).
Hooks
useFlag(key, defaultValue)
Returns the resolved flag value. Falls back to defaultValue while loading or if the flag does not exist.
const isEnabled = useFlag('dark-mode', false);
const variant = useFlag('checkout-flow', 'control');useFlagDetail(key)
Returns detailed evaluation information including metadata.
const { value, enabled, metadata, loading } = useFlagDetail('new-checkout');
// metadata contains: category, purpose, owners, isPermanent, expiresAt, tagsuseFlagsByCategory(category)
Returns all flags matching the given category.
const experiments = useFlagsByCategory('experiment');
const releases = useFlagsByCategory('release');Categories: 'release' | 'feature' | 'experiment' | 'ops' | 'permission' | 'envvar'
useExpiredFlags()
Returns all non-permanent flags whose expiresAt date is in the past. Useful for admin dashboards.
const expired = useExpiredFlags();useFlagsVersion()
Returns the project's flag-set version last loaded from the server (number), or null before the first successful fetch / in file mode. The version advances on any change to the project's flag state, so it validates exactly which flag set the app is serving. Re-renders when a refetch changes the version.
const version = useFlagsVersion();
return <span>flags v{version ?? '—'}</span>;useDispatch(operation)
Returns the resolved handler for a registered operation based on current flag state. See Register / Dispatch Pattern below.
const checkout = useDispatch<() => Promise<void>>('checkout');
await checkout();useDeploySentry()
Returns the raw DeploySentryClient instance for advanced use-cases.
const client = useDeploySentry();Register / Dispatch Pattern
The register/dispatch pattern centralizes all flag-gated behavior in one place instead of scattering if/else checks across components.
Setup (single-point registration)
Create one registration file that runs at app initialization:
// src/flags/registrations.ts
import type { DeploySentryClient } from '@dr-sentry/react';
import { legacySearch, vectorSearch } from '../search';
import { classicCheckout, newCheckout } from '../checkout';
export function registerFlags(client: DeploySentryClient) {
// Search — default handler, then flag-gated override
client.register('search', legacySearch);
client.register('search', vectorSearch, 'vector-search-v2');
// Checkout
client.register('checkout', classicCheckout);
client.register('checkout', newCheckout, 'new-checkout-flow');
}Call registerFlags(client) after the client initializes (e.g. in the provider setup or an app-level effect).
Usage in components
import { useDispatch } from '@dr-sentry/react';
function SearchBar() {
const search = useDispatch<(query: string) => Promise<Results>>('search');
return (
<input onChange={(e) => search(e.target.value).then(setResults)} />
);
}How it works
client.register(operation, handler, flagKey?)— Register a handler for a named operation. WithflagKey, it's only selected when that flag is enabled. WithoutflagKey, it's the default fallback.useDispatch(operation)— Returns the first registered handler whose flag is enabled, or the default handler. The component never knows about flags.
Why single-point registration
- One file shows every flag-gated behavior in the app
- Easy auditing — search for a flag key and find every behavior it controls
- Simple cleanup when a flag is retired (remove the registration, keep the handler)
- LLMs and code review tools can read one file to understand all flag-gated behavior
Real-Time Updates
The provider automatically opens an SSE connection to receive flag updates in real time. When a flag changes on the server, all components consuming that flag re-render immediately. The connection reconnects automatically with exponential backoff if it drops.
SSR Compatibility
Hooks return default/empty values during server-side rendering. Flags are fetched client-side after the provider mounts.
Types
All types are exported from the package:
import type {
Flag,
FlagCategory,
FlagDetail,
FlagMetadata,
ProviderProps,
UserContext,
} from '@dr-sentry/react';Authentication
All requests use an API key passed in the Authorization header:
Authorization: ApiKey <your-api-key>Pass the key via the provider's apiKey prop. The SDK sets the header automatically.
Session Consistency
Bind evaluations to a session so the server caches results for a consistent user experience:
<DeploySentryProvider
apiKey="ds_key_xxxxxxxxxxxx"
baseURL="https://api.dr-sentry.com"
environment="production"
project="my-app"
application="my-web-app"
sessionId={`user:${userId}`}
>
<App />
</DeploySentryProvider>const client = useDeploySentry();
await client.refreshSession();- The session ID is sent as an
X-DeploySentry-Sessionheader on every request. - The server caches evaluation results per session for 30 minutes (sliding TTL).
- Omit the session ID to always get fresh evaluations on each request.
License
Apache-2.0
