gb-feature-flag
v0.0.2
Published
Modular feature flag components and hooks for React applications using GrowthBook
Downloads
25
Maintainers
Readme
GB Feature Flag
Modular feature flag components and hooks for React applications using GrowthBook.
A lightweight, type-safe React library that simplifies feature flag integration with GrowthBook. Perfect for A/B testing, gradual rollouts, and remote configuration in modern React applications.
Features
- 🚀 Simple, declarative API for feature flags
- 🔒 Route protection with feature-based access control
- 🎣 Custom hooks for component-level logic
- 📦 Full TypeScript support with strict typing
- ⚛️ React 18 & 19 compatible
- 🔄 Integrates seamlessly with React Router v6
Installation
npm install gb-feature-flagQuick Setup
1. Wrap your app with the provider
import { GBFeatureFlagProvider } from 'gb-feature-flag';
function App() {
return (
<GBFeatureFlagProvider
growthbookClientKey="your-growthbook-client-key"
enableDevMode={process.env.NODE_ENV === 'development'}
attributes={{
id: 'user123',
email: '[email protected]',
plan: 'premium'
}}
loadingComponent={<div>Loading features...</div>}
onReady={() => console.log('GrowthBook ready!')}
>
<YourApp />
</GBFeatureFlagProvider>
);
}2. Integration with React Router
import { createBrowserRouter } from "react-router";
import { GBFeatureFlagProvider, ProtectedRoute } from 'gb-feature-flag';
const router = createBrowserRouter([
{
path: '/',
Component: DefaultLayout,
children: [
// Public route
{
index: true,
lazy: async () => {
const { default: HomeComponent } = await import("./view/Home");
return { Component: HomeComponent };
}
},
// Protected route - requires 'admin-panel' feature
{
path: 'admin',
lazy: async () => {
const { default: AdminComponent } = await import("./view/Admin");
return {
Component: () => (
<ProtectedRoute
feature="admin-panel"
redirectTo="/unauthorized"
>
<AdminComponent />
</ProtectedRoute>
),
};
}
},
// Premium route with fallback
{
path: 'premium',
lazy: async () => {
const { default: PremiumComponent } = await import("./view/Premium");
return {
Component: () => (
<ProtectedRoute
feature="premium-access"
fallback={<div>Please upgrade to access premium features</div>}
>
<PremiumComponent />
</ProtectedRoute>
),
};
}
}
]
}
]);Usage Patterns
Hooks (Recommended for logic)
import { useFeatureIsOn, useFeatureValue } from 'gb-feature-flag';
function MyComponent() {
const isNewDashboard = useFeatureIsOn('new-dashboard');
const buttonColor = useFeatureValue('button-color', 'blue');
return (
<div>
{isNewDashboard && <NewDashboard />}
<button style={{ backgroundColor: buttonColor }}>
Click me
</button>
</div>
);
}Components (Recommended for UI)
import {
FeatureFlag,
FeatureEnabled,
FeatureDisabled,
FeatureValue
} from 'gb-feature-flag';
function MyComponent() {
return (
<div>
{/* Simple feature flag */}
<FeatureFlag featureKey="beta-feature">
<BetaFeatureComponent />
</FeatureFlag>
{/* Feature with fallback */}
<FeatureFlag
featureKey="premium-feature"
fallback={<UpgradePrompt />}
>
<PremiumContent />
</FeatureFlag>
{/* Feature value with render prop */}
<FeatureValue<string> featureKey="welcome-message" defaultValue="Welcome!">
{(message) => <h1>{message}</h1>}
</FeatureValue>
</div>
);
}Route Protection
import { ProtectedRoute } from 'gb-feature-flag';
function AppRoutes() {
return (
<Routes>
<Route path="/dashboard" element={
<ProtectedRoute feature="dashboard-access">
<Dashboard />
</ProtectedRoute>
} />
<Route path="/admin" element={
<ProtectedRoute
feature="admin-access"
redirectTo="/login"
>
<AdminPanel />
</ProtectedRoute>
} />
</Routes>
);
}API Reference
Components
| Component | Description |
|-----------|-------------|
| GBFeatureFlagProvider | Context provider that wraps your app with GrowthBook configuration |
| FeatureFlag | Conditional rendering based on feature flag state with optional fallback |
| FeatureEnabled | Renders children only when the feature is enabled |
| FeatureDisabled | Renders children only when the feature is disabled |
| FeatureValue<T> | Render prop component that passes feature value to children |
| ProtectedRoute | Route protection with redirect or fallback support |
| FeatureRoute | Simple wrapper for feature-based routing |
| withFeatureFlag | HOC for adding feature flag protection to components |
Hooks
| Hook | Description |
|------|-------------|
| useFeatureIsOn(featureKey) | Returns boolean indicating if feature is enabled |
| useFeatureValue(featureKey, defaultValue) | Returns the feature value with fallback |
| useGrowthBook() | Access to the underlying GrowthBook instance |
| useFeatures(featureKeys) | Batch multiple feature checks into a single object |
| useFeatureWithAttributes(featureKey, attributes) | Check feature with dynamic user attributes |
Types
| Type | Description |
|------|-------------|
| GBFeatureFlagProviderProps | Provider configuration options |
| FeatureFlagProps | Feature flag wrapper props |
| FeatureValueProps<T> | Feature value component props |
| ProtectedRouteProps | Protected route configuration |
| UserAttributes | User attribute object type |
| FeatureFlagConfig | Feature flag configuration type |
| GrowthBookFeature | GrowthBook feature definition |
| JSONValue | Valid JSON value types (string \| number \| boolean \| null \| object \| array) |
Project Structure
gb-feature-flag/
├── src/
│ ├── lib/
│ │ ├── components/
│ │ │ ├── index.ts # Component exports
│ │ │ ├── FeatureFlag/ # Basic feature flag wrapper
│ │ │ ├── FeatureEnabled/ # Render when enabled
│ │ │ ├── FeatureDisabled/ # Render when disabled
│ │ │ ├── FeatureValue/ # Render prop for values
│ │ │ ├── ProtectedRoute/ # Route protection
│ │ │ └── Provider/ # GrowthBook context provider
│ │ ├── hooks/
│ │ │ ├── index.ts # Hook exports
│ │ │ └── index.test.ts # Hook tests
│ │ ├── types.ts # TypeScript definitions
│ │ └── gb-feature-flag.ts # Main component
│ └── index.ts # Public API exports
├── package.json
├── tsconfig.json
├── vite.config.ts
└── README.mdExamples
Basic Usage
// Boolean feature flag
<FeatureEnabled featureKey="new-dashboard">
<NewDashboard />
</FeatureEnabled>
// Feature with custom value
<FeatureValue<string> featureKey="theme-color" defaultValue="blue">
{(color) => <div style={{ color }}>Themed content</div>}
</FeatureValue>
// Protected route
<ProtectedRoute feature="premium-features" redirectTo="/upgrade">
<PremiumContent />
</ProtectedRoute>Advanced Usage
// Multiple features
const features = useFeatures(['feature1', 'feature2', 'feature3']);
// Dynamic attributes
const userAttributes = useFeatureWithAttributes('beta-access', {
userId: '123',
plan: 'premium'
});
// Higher-order component
const ProtectedComponent = withFeatureFlag('admin-access', {
redirectTo: '/unauthorized'
})(AdminPanel);Development
Building
npm run build
npm run build:dev # Development build
npm run build:prod # Production buildTesting
The library includes comprehensive unit tests for all hooks. Run tests with:
npm testPublishing
npm run prepublishOnly # Build before publishing
npm publishTypeScript Support
Full TypeScript support with strict typing:
// Type-safe feature values
<FeatureValue<{name: string; count: number}> featureKey="config" defaultValue={{name: 'default', count: 0}}>
{(config) => <div>{config.name}: {config.count}</div>}
</FeatureValue>Best Practices
- Use hooks for component logic - Use
useFeatureIsOnanduseFeatureValueinside components for business logic - Use components for conditional UI - Use
FeatureEnabled/FeatureDisabledfor declarative rendering - Group related features - Organize features hierarchically in GrowthBook (e.g.,
admin.panel.v2) - Use descriptive names - Prefix features with domain (e.g.,
checkout.new-flow,dashboard.beta) - Set sensible defaults - Always provide fallback values for feature values
- Handle loading states - Use the
loadingComponentprop in provider for initial load - Clean up regularly - Remove unused features to keep your dashboard manageable
Links
License
MIT © Msight Dashboard
