@localflag/react
v0.0.6
Published
Type-safe feature flags for React with built-in DevTools
Maintainers
Readme
@localflag/react
Type-safe feature flags for React with built-in LocalFlagDevTools.
Website · Documentation · Demo · GitHub
Installation
npm install @localflag/reactQuick Start
import { FeatureFlagProvider, useFeatureFlag, LocalFlagDevTools } from '@localflag/react';
// 1. Define your flags
const defaultFlags = {
darkMode: false,
newCheckout: true,
maxItems: 10,
} as const;
// 2. Create a type for your flags
type AppFlags = typeof defaultFlags;
// 3. Wrap your app with the provider
function App() {
return (
<FeatureFlagProvider<AppFlags> defaultFlags={defaultFlags}>
<MyApp />
<LocalFlagDevTools /> {/* Optional: adds a floating panel to toggle flags */}
</FeatureFlagProvider>
);
}
// 4. Use flags in your components
function MyComponent() {
const isDarkMode = useFeatureFlag<AppFlags>('darkMode');
return <div className={isDarkMode ? 'dark' : 'light'}>...</div>;
}API
FeatureFlagProvider
The context provider that makes feature flags available to your app.
<FeatureFlagProvider<AppFlags>
defaultFlags={defaultFlags}
storageKey="my-app-flags" // Optional: localStorage key (default: 'feature-flags')
persistOverrides={true} // Optional: persist overrides to localStorage (default: true)
>
{children}
</FeatureFlagProvider>Hooks
useFeatureFlag<T>(flagName)
Returns true if the flag is enabled (truthy), false otherwise.
const isEnabled = useFeatureFlag<AppFlags>('darkMode');
// Returns: booleanuseFeatureFlagValue<T>(flagName)
Returns the actual value of the flag.
const maxItems = useFeatureFlagValue<AppFlags>('maxItems');
// Returns: 10 (the actual value)useFeatureFlags<T>()
Returns all current flag values.
const flags = useFeatureFlags<AppFlags>();
// Returns: { darkMode: false, newCheckout: true, maxItems: 10 }useFeatureFlagControls<T>()
Returns functions to control flags programmatically.
const { setFlag, resetFlags } = useFeatureFlagControls<AppFlags>();
// Set a specific flag
setFlag('darkMode', true);
// Reset all flags to defaults
resetFlags();Components
FeatureFlag
Conditionally render content based on a flag.
import { FeatureFlag } from '@localflag/react';
<FeatureFlag<AppFlags> flag="newCheckout">
<NewCheckoutFlow />
</FeatureFlag>
// With fallback
<FeatureFlag<AppFlags> flag="newCheckout" fallback={<OldCheckout />}>
<NewCheckoutFlow />
</FeatureFlag>LocalFlagDevTools
A floating panel for toggling flags during development.
import { LocalFlagDevTools } from '@localflag/react';
<LocalFlagDevTools
position="bottom-right" // 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left'
defaultOpen={false} // Start expanded or collapsed
/>TypeScript
The library is fully typed. Define your flags with as const to get full type inference:
const defaultFlags = {
darkMode: false,
newFeature: true,
apiVersion: 'v2',
maxRetries: 3,
} as const;
type AppFlags = typeof defaultFlags;
// Now all hooks will autocomplete flag names and infer value types
const version = useFeatureFlagValue<AppFlags>('apiVersion');
// TypeScript knows this is 'v2' (string literal type)Config File Pattern
For larger projects, you can use defineFlags to create a centralized config file:
// flags.config.ts
import { defineFlags } from '@localflag/react';
export const flags = defineFlags({
darkMode: false,
newCheckout: true,
maxRetries: 3,
});
export type AppFlags = typeof flags;Then import it in your app:
// App.tsx
import { flags, AppFlags } from './flags.config';
import { FeatureFlagProvider, useFeatureFlag } from '@localflag/react';
function App() {
return (
<FeatureFlagProvider<AppFlags> defaultFlags={flags}>
<MyApp />
</FeatureFlagProvider>
);
}Benefits:
- All flags managed in one place
- Easy to export and share types across your app
- Enables future tooling integration
Persistence
By default, flag overrides are persisted to localStorage. This means:
- Flags you toggle in LocalFlagDevTools persist across page reloads
- Each user can have their own overrides for testing
- Call
resetFlags()to clear all overrides and return to defaults
To disable persistence:
<FeatureFlagProvider defaultFlags={defaultFlags} persistOverrides={false}>License
MIT
