gb-feature-flag
v0.0.2
Published
Modular feature flag components and hooks for React applications using GrowthBook
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
