Feature Flag Components for Launch Darkly that work seemlessly with redux
ld-redux-components is a helper library for Launch Darkly in React that relies on your feature flags being stored in redux.
It is recommended that you use ld-redux, as it provides an easy and clean way to connect Launch Darkly flags to redux, and works as a nice wrapper for ldclient-js.
You should define your Launch Darkly redux strategy before using ld-redux-components. It won't work without your flags in redux. As stated above, ld-redux is the best option, but the only compatability requirement is that you nest your flags in an object of key/value pairs under a key in the base of your redux store. Here is an example of what your store might look like,
{
...,
"LD": {
"debugger": true,
"newFeature": "on",
"tasks": false,
},
...,
}
(note: the above example is using camelCase
as ld-redux does, but you can store the flags as lisp-case
if you so choose)
yarn add ld-redux-components
# or
npm install ld-redux-components
- In your client bootstrap, initialize ld-redux-components:
import { ldrComponentConfig } from 'ld-redux-components';
//This value will be the key in your redux store where your flags are stored
ldrComponentConfig.init({
reduxKey: "LD"
});
- Import and use
Feature
andVariant
helper components in a component:
import React, { Component } from 'react';
import { Feature, Variant } from 'ld-redux-components';
import { Item } from '<my-app>/item';
export default class FeatureDisplay extends Component {
render() {
return (
<Feature flagId="testFlagId">
<Variant variation={ true }>
<Item name="FLAG IS TRUE" icon="smile" color="green" />
</Variant>
<Variant variation={ false }>
<Item name="FLAG IS FALSE" icon="frown" color="red" />
</Variant>
<Variant isDefault>
<Item name="FLAG IS NULL/UNDEFINED" icon="meh" color="blue" />
</Variant>
</Feature>
);
}
}
Boom! ld-redux-components
is working! Notice how there is no need to connect your component, as the Feature
component does that heavy lifting for you. Just add Feature
and Variant
components where you please.
name | type | required | default | description |
---|---|---|---|---|
flagName |
string | true |
- | name of flag stored in redux |
variation |
string, bool, array, null | false |
- | value of flag |
onReady |
function | false |
- | callback fired when ld connected |
waitForLD |
bool | false |
false |
wait to render until ld connected |
liveUpdate |
bool | false |
true |
rerender after initial LD load |
Feature
is primarily used as a wrapper ofVariant
components.- For cases where you only need to either show or not show something, you can set the
variation
prop. This allows you to avoid using unnecessaryVariant
components when you only have one variation you care about. variation
should not be set if you plan on usingVariant
components underneathFeature
.
Feature
import React, { Component } from 'react';
import { Feature, Variant } from 'ld-redux-components';
import { Item } from '<my-app>/item';
export default class Display extends Component {
render() {
return (
<Feature flagId="testFlagId">
<Variant variation={ true }>
<Item name="FLAG IS TRUE" icon="smile" color="green" />
</Variant>
<Variant variation={ false }>
<Item name="FLAG IS FALSE" icon="frown" color="red" />
</Variant>
</Feature>
);
}
}
Feature
with variation
prop set and no Variant
components
import React, { Component } from 'react';
import { Feature } from 'ld-redux-components';
import { Item } from '<my-app>/item';
export default class Display extends Component {
render() {
return (
<Feature flagId="testFlagId" variation={ true }>
<Item name="FLAG IS TRUE" icon="smile" color="green" />
</Feature>
);
}
}
Variant
MUST be defined underneath a Feature
component
name | type | required | default | description |
---|---|---|---|---|
variation |
string, bool, array, null | false |
- | value of flag |
isDefault |
bool | false |
false | display on null/undefined variation |
- Must be defined underneath
Feature
component - Will always evaluate against the closest parent
Feature
component (yes, this means you can nest Feature/Variants in other Feature/Variants, and Variants can be deeply nested under Features) isDefault
can be used as handler in case a flag is undefined or set to null. You can use this in combination withvariation
, or by itself
Two Variants
import React, { Component, Fragment } from 'react';
import { Feature, Variant } from 'ld-redux-components';
import { Item } from '<my-app>/item';
export default class Display extends Component {
render() {
return (
<Feature flagId="testFlagId">
<Variant variation={ true }>
<Item name="FLAG IS TRUE" icon="smile" color="green" />
</Variant>
<Variant variation={ false }>
<Item name="FLAG IS FALSE" icon="frown" color="red" />
</Variant>
</Feature>
);
}
}
Multiple Variants
import React, { Component, Fragment } from 'react';
import { Feature, Variant } from 'ld-redux-components';
import { Item } from '<my-app>/item';
export default class Display extends Component {
render() {
return (
<Feature flagId="testFlagId">
<Variant variation="control">
<Item name="FLAG IS TRUE" icon="smile" color="green" />
</Variant>
<Variant variation={ ["treatment", "none"] }>
<Item name="FLAG IS FALSE" icon="frown" color="red" />
</Variant>
</Feature>
);
}
}
Variant with isDefault
import React, { Component, Fragment } from 'react';
import { Feature, Variant } from 'ld-redux-components';
import { Item } from '<my-app>/item';
export default class Display extends Component {
render() {
return (
<Feature flagId="testFlagId">
<Variant variation={ true }>
<Item name="FLAG IS TRUE" icon="smile" color="green" />
</Variant>
<Variant isDefault>
<Item name="FLAG IS NULL/UNDEFINED" icon="meh" color="yellow" />
</Variant>
</Feature>
);
}
}
Deeply Nested Variant
import React, { Component, Fragment } from 'react';
import { Feature, Variant } from 'ld-redux-components';
import { Item } from '<my-app>/item';
import { SomeOtherComponent } from '<my-app>/someOtherComponent';
export default class Display extends Component {
render() {
return (
<Feature flagId="testFlagId">
<SomeOtherComponent>
<Variant variation={ true }>
<Item name="FLAG IS TRUE" icon="smile" color="green" />
</Variant>
</SomeOtherComponent>
<Variant variation={ false }>
<Item name="FLAG IS FALSE" icon="frown" color="red" />
</Variant>
</Feature>
);
}
}
Feature/Variants Nested under Feature/Variants
import React, { Component, Fragment } from 'react';
import { Feature, Variant } from 'ld-redux-components';
import { Item } from '<my-app>/item';
export default class Display extends Component {
render() {
return (
<Feature flagId="testFlagId">
<Variant variation={ true }>
<Feature flagId="anotherFlagId">
<Variant variation="on">
<Item name="FLAG IS ON" icon="smile" color="green" />
</Variant>
<Variant variation="off">
<Item name="FLAG IS OFF" icon="frown" color="red" />
</Variant>
</Feature>
</Variant>
<Variant variation={ false }>
<Item name="FLAG IS FALSE" icon="frown" color="red" />
</Variant>
</Feature>
);
}
}
For a working example, check this example app out (you'll need to provide your own credentials and flags to get things working locally)
Welcome!