Skip to content

Instantly share code, notes, and snippets.

@tubalmartin
Last active March 12, 2019 15:42
Show Gist options
  • Save tubalmartin/0593cb3967e694dda6d59f51c8f2e03a to your computer and use it in GitHub Desktop.
Save tubalmartin/0593cb3967e694dda6d59f51c8f2e03a to your computer and use it in GitHub Desktop.
import React, {Component} from 'react';
import PropTypes from 'prop-types';
import {connect} from 'react-redux';
import VisibilitySensor from 'react-visibility-sensor';
import {logExperiment} from '@homeaway/abacus-client-utils';
const style = {
minHeight: '1px',
marginTop: '-1px',
display: 'block'
};
const mapStateToProps = ({abacus}) => ({
experiments: abacus
});
class AbacusExperiment extends Component {
/** Shared across component instances */
static exposedExperiments = [];
static propTypes = {
/** Experiment name */
name: PropTypes.string.isRequired,
/** Abacus experiments from Redux */
experiments: PropTypes.object.isRequired,
/** Whether to wrap the rendered code inside a VisibilitySensor instance */
checkVisibility: PropTypes.bool,
/** Nodes to render when experiment value is 0 */
control: PropTypes.node,
/** Nodes to render when experiment value is 1 */
variant: PropTypes.node,
}
static defaultProps = {
checkVisibility: true,
control: null,
variant: null
}
getExperimentValue() {
const {name, experiments} = this.props;
return typeof experiments[name] === 'object'
? experiments[name].value
: -1;
}
handleVisibility = (experimentName) => (isVisible) => {
if (isVisible && !this.constructor.exposedExperiments.includes(experimentName)) {
this.constructor.exposedExperiments.push(experimentName);
logExperiment(experimentName);
}
}
wrapWithVisibilitySensor(nodes) {
const {name, minTopValue} = this.props;
return (
<VisibilitySensor
partialVisibility
minTopValue={minTopValue}
delayedCall
onChange={this.handleVisibility(name)}
>
{nodes && <div style={{minHeight: '1px'}}>{nodes}</div> || <s style={style} />}
</VisibilitySensor>
);
}
renderControlOrVariant(experimentValue) {
const {control, variant} = this.props;
switch (experimentValue) {
case 0:
return control instanceof Function ? control() : control;
case 1:
return variant instanceof Function ? variant() : variant;
default:
return null;
}
}
renderChildren(experimentValue) {
const {children} = this.props;
return children instanceof Function ? children(experimentValue) : children;
}
render() {
const {checkVisibility, control, variant} = this.props;
const experimentValue = this.getExperimentValue();
const nodes = control && variant
? this.renderControlOrVariant(experimentValue)
: this.renderChildren(experimentValue);
return checkVisibility === true
? this.wrapWithVisibilitySensor(nodes)
: nodes;
}
}
export default connect(mapStateToProps)(AbacusExperiment);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment