Last active
August 30, 2018 20:12
-
-
Save akdetrick/4c6d4373ea2633664b7d6e64b54e68c5 to your computer and use it in GitHub Desktop.
React component for A/B testing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* This is some feature component in which we're running | |
* two experiments, `radExperiment` and `coolExperiment`. | |
* | |
* Each experiment can either be `true` (variant), or | |
* `false` (control). The service probably runs more than | |
* one control, but the front end need only know if | |
* it's getting "variant" or not. | |
*/ | |
const FeatureComponent = (props) => { | |
const { | |
experiments, | |
} = this.props; | |
return ( | |
<dl> | |
<dt>Is this user in coolExperiment variant?</dt> | |
{experiments.coolExperiment | |
? <dd>Cool Variant!</dd> | |
: <dd>Cool Control.</dd> | |
} | |
<dt>Is this user in radExperiment variant?</dt> | |
{experiments.radExperiment | |
? <dd>Rad Variant!</dd> | |
: <dd>Rad Control.</dd> | |
} | |
</dl> | |
); | |
} | |
// the `withExperiments` HOC adds the `experiments` prop to the wrapped component | |
export.default FeatureComponentWithExperiment = withExperiments( | |
FeatureComponent, | |
['coolExperiment', 'radExperiment'] | |
); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* this should live in `src/client/modules/common/decorators/withExperiment` */ | |
/** | |
* @param {ReactElement} WrappedComponent component that will be provided `experiments` prop | |
* @param {Array} experimentNames experiment name strings | |
*/ | |
const withExperiments = (WrappedComponent, experimentNames) => { | |
// define the prop as an object with the shape; | |
// { | |
// experimentName1: Boolean(user in variant?), | |
// experimentName2: Boolean(user in variant?), | |
// } | |
// | |
const experimentsProp = experimentNames | |
.reduce((obj, name) => { | |
// getExperimentState could be checking app state, | |
// dispatching an action, selector, or something else that | |
// provides information about the state of the experiment | |
// for the current user | |
obj[name] = getExperimentState(name); | |
// The experiment service should always return "control" for errors | |
// or undefined experiments. The front end _should not_ define a | |
// default value here; the service should be the point of truth. | |
}, {}); | |
const ComponentWithExperiment = (props) => ( | |
<WrappedComponent | |
experiments={experimentsProp} | |
{...props} | |
/> | |
); | |
ComponentWithExperiment.propTypes = { | |
experiments: PropTypes.object | |
}; | |
return ComponentWithExperiment; | |
}; | |
export default withExperiment; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment