@uikudo/useflag
v0.2.0
Published
A lightweight React hook for feature flags
Maintainers
Readme
@uikudo/useflag
A lightweight, simple feature flag library for React applications with local override support.
Features
- FlagProvider: React Context provider for default flag configuration
- useFlag Hook: Simple hook that returns boolean values
- Priority System: Local override → Provider value → false
- localStorage Persistence: Override flags persist across sessions
- TypeScript Support: Full TypeScript definitions included
- Tiny Bundle Size: Minimal footprint for your application
- SSR Safe: Works with server-side rendering
Installation
npm install @uikudo/useflag
# or
pnpm add @uikudo/useflag
# or
yarn add @uikudo/useflagQuick Start
1. Wrap your app with FlagProvider
import { FlagProvider } from '@uikudo/useflag';
ReactDOM.createRoot(document.getElementById('root')!).render(
<FlagProvider flags={{ darkMode: true, premium: false }}>
<App />
</FlagProvider>
);2. Use flags in your components
import { useFlag } from '@uikudo/useflag';
function MyComponent() {
const isDarkMode = useFlag('darkMode');
const isPremium = useFlag('premium');
return (
<div className={isDarkMode ? 'dark' : 'light'}>
{isPremium && <PremiumFeature />}
</div>
);
}3. Override flags locally (optional)
import { setFlagOverride, clearFlagOverride } from '@uikudo/useflag';
// Set an override
setFlagOverride('darkMode', false);
// Clear an override (falls back to provider value)
clearFlagOverride('darkMode');API Reference
<FlagProvider>
Provides default flag configuration to your application.
Props:
flags?: FlagConfig- Object mapping flag names to boolean valueschildren: ReactNode- Your application components
Example:
<FlagProvider flags={{
darkMode: true,
newFeature: false,
beta: true
}}>
<App />
</FlagProvider>useFlag(name: string): boolean
Hook to access a feature flag value.
Parameters:
name: string- The name of the flag
Returns:
boolean- The current flag value
Priority:
- Local override (from localStorage)
- Provider value (from FlagProvider)
false(default)
Example:
const isDarkMode = useFlag('darkMode');
const isNewFeature = useFlag('newFeature');setFlagOverride(name: string, value: boolean): void
Set a local override for a flag. Stored in localStorage and persists across sessions.
Parameters:
name: string- Flag namevalue: boolean- Flag value
Example:
setFlagOverride('darkMode', true);clearFlagOverride(name: string): void
Clear a local override. Flag will fall back to provider value or false.
Parameters:
name: string- Flag name
Example:
clearFlagOverride('darkMode');clearAllFlagOverrides(): void
Clear all local overrides.
Example:
clearAllFlagOverrides();getAllFlagOverrides(): FlagConfig
Get all current local overrides.
Returns:
FlagConfig- Object with all override flags
Example:
const overrides = getAllFlagOverrides();
console.log(overrides); // { darkMode: true, premium: false }Priority System
Flags are resolved with the following priority:
Local Override (highest priority)
- Stored in
localStoragewith keyuseflag:overrides - Persists across browser sessions
- Set via
setFlagOverride()
- Stored in
Provider Value
- Defined in
<FlagProvider flags={...}> - Application-level defaults
- Defined in
Default Value (lowest priority)
- Always
falseif not defined elsewhere
- Always
localStorage Structure
Overrides are stored in localStorage under the key useflag:overrides:
{
"darkMode": true,
"premium": false,
"beta": true
}TypeScript
Full TypeScript support included:
import type { FlagConfig } from '@uikudo/useflag';
const myFlags: FlagConfig = {
darkMode: true,
premium: false,
};Examples
Basic Usage
import { FlagProvider, useFlag } from '@uikudo/useflag';
function App() {
return (
<FlagProvider flags={{ darkMode: true }}>
<Dashboard />
</FlagProvider>
);
}
function Dashboard() {
const isDarkMode = useFlag('darkMode');
return (
<div className={isDarkMode ? 'dark-theme' : 'light-theme'}>
Dashboard
</div>
);
}With Local Overrides
import { useFlag, setFlagOverride } from '@uikudo/useflag';
function FeatureToggle() {
const isEnabled = useFlag('newFeature');
return (
<div>
<p>Feature is {isEnabled ? 'enabled' : 'disabled'}</p>
<button onClick={() => setFlagOverride('newFeature', !isEnabled)}>
Toggle Feature
</button>
</div>
);
}Development Tools
import { getAllFlagOverrides, clearAllFlagOverrides } from '@uikudo/useflag';
function DevTools() {
const [overrides, setOverrides] = useState(getAllFlagOverrides());
const handleReset = () => {
clearAllFlagOverrides();
setOverrides({});
};
return (
<div>
<h3>Current Overrides</h3>
<pre>{JSON.stringify(overrides, null, 2)}</pre>
<button onClick={handleReset}>Reset All</button>
</div>
);
}Best Practices
- Define flags in one place: Use
FlagProviderat your app root with all flags - Use descriptive names:
darkMode,premiumFeatures,experimentalUI - Document your flags: Keep a list of all flags and their purposes
- Clean up old flags: Remove unused flags from your codebase
- Dev tools: Create a dev panel to toggle flags during development
Browser Support
Works in all modern browsers that support:
- React 18+
- localStorage
- CustomEvent API
License
MIT
Contributing
Contributions welcome! Please open an issue or PR.
Author
uikudo
