React Feature Toggles attempts to satisfy the following requirements:
- Universal - server and client side
- Conditionally execute code based on the presence or absence of a specific feature
- Toggle features on with url parameters
- Feature Dependency - if a feature depends on a another feature that is disabled, then neither of them should execute
npm install --save @paralleldrive/react-feature-toggles
import { FAQComponent } from '../features/faq';
import { NotFoundComponent } from '../features/404-page';
import { FeatureToggles, Feature } from '@paralleldrive/react-feature-toggles';
const features = ['faq', 'foo', 'bar'];
const MyApp = () => {
return (
<FeatureToggles features={features}>
<Feature name="faq" inactiveComponent={NotFoundComponent} activeComponent={FAQComponent}/>
</FeatureToggles>
)
}
FeatureToggles
is a provider component.
props
- features = []
import { FeatureToggles } from '@paralleldrive/react-feature-toggles';
const features = ['foo', 'bar', 'baz', 'cat'];
const MyApp = () => {
return (
<FeatureToggles features={features}>
{... stuff}
</FeatureToggles>
)
}
Feature
is a consumer component.
If the feature is enabled then the activeComponent will render else it renders the inactiveComponent.
Feature takes these props
- name = ""
- inactiveComponent = noop
- activeComponent = null
import { FeatureToggles, Feature } from '@paralleldrive/react-feature-toggles';
const MyApp = () => {
return (
<FeatureToggles>
<Feature name="faq" inactiveComponent={NotFoundComponent} activeComponent={FAQComponent}/>
<Feature name="help" inactiveComponent={NotFoundComponent} activeComponent={HelpComponent}/>
</FeatureToggles>
)
}
Alternatively, you can use Feature
as a render prop component. Do this by passing a function as the children to the Feature
component. Note: This will only work if an activeComponent
is not provided.
import { FeatureToggles, Feature, isActive } from '@paralleldrive/react-feature-toggles';
const MyApp = () => {
return (
<FeatureToggles>
<Feature>
{({ features }) => isActive('bacon', features) ? 'The bacon feature is active' : 'Bacon is inactive' }
</Feature>
</FeatureToggles>
)
}
({ features = [...String] } = {}) => Component => Component
You can use withFeatureToggles
to compose your page functionality.
import MyPage from '../feautures/my-page';
import { withFeatureToggles } from '@paralleldrive/react-feature-toggles';
const features = ['foo', 'bar', 'baz', 'cat'];
export default = compose(
withFeatureToggles({ features }),
// ... other page HOC imports
hoc1,
hoc2,
);
Depending on your requirements, you might need something slightly different than the default withFeatureToggles
. The default withFeatureToggles
should serve as a good example to create your own.
(inactiveComponent, feature, activeComponent) => Component
configureFeature
is a higher order component that allows you to configure a Feature
component. configureFeature is auto curried so that you can partially apply the props.
import { FeatureToggles } from '@paralleldrive/react-feature-toggles';
const NotFoundPage = () => <div>404</div>;
const ChatPage = () => <div>Chat</div>;
const featureOr404 = configureFeature(NotFoundPage);
const Chat = featureOr404('chat', ChatPage);
const features = ['foo', 'bar', 'chat'];
const myPage = () => (
<FeatureToggles features={features}>
<Chat />
</FeatureToggles>
);
interface Feature {
name: String,
isActive: false,
dependencies?: [...String]
}
([...Feature]) => [...String]
Takes an array of feature objects and returns an array of enabled feature names.
(query = {}) => [...String]
Takes a query object and returns an array of enabled feature names.
const query = { ft='foo,bar,help' }
parseQuery(query); // ['foo', 'bar', 'help']
(...[...String]) => [...String]
Merge feature names without duplicating.
const currentFeatures = ['foo', 'bar', 'baz'];
mergeFeatures(currentFeatures, ['fish', 'bar', 'cat']); // ['foo', 'bar', 'baz', 'fish', 'cat']
([...String], [...String]) => [...String]
Removes feature names
const currentFeatures = ['foo', 'bar', 'baz', 'cat'];
deactivate(currentFeatures, ['fish', 'bar', 'cat']); // ['foo', 'baz']
(String, [...String]) => boolean
Returns true if a feature name is in the array else it returns false.
const currentFeatures = ['foo', 'bar', 'baz'];
isActive('bar', currentFeatures); // true
isActive('cat', currentFeatures); // false
In v2, query logic has been moved out of the provider component. You should now handle this logic before passing features to FeatureToggles
import { FeatureToggles, mergeFeatures, parseQuery } from '@paralleldrive/react-feature-toggles';
import parse from 'url-parse';
const url = 'https://domain.com/foo?ft=foo,bar';
const query = parse(url, true);
const initialFeatures = ['faq', 'foo', 'bar'];
const features = mergeFeatures(initialFeatures, parseQuery(query));
const MyApp = () => {
return (
<FeatureToggles features={features}>
{...stuff}
</FeatureToggles>
)
}