Skip to content

Instantly share code, notes, and snippets.

@starandtina
Forked from RStankov/EnabledFeature.js
Created January 22, 2017 13:13
Show Gist options
  • Save starandtina/28251f930c60d0b74bc38bfc565f577c to your computer and use it in GitHub Desktop.
Save starandtina/28251f930c60d0b74bc38bfc565f577c to your computer and use it in GitHub Desktop.

Revisions

  1. @RStankov RStankov revised this gist Jan 6, 2017. 4 changed files with 14 additions and 13 deletions.
    1 change: 1 addition & 0 deletions createFeatureFlaggedContainer.js
    Original file line number Diff line number Diff line change
    @@ -14,6 +14,7 @@ export default function createFeatureFlaggedContainer({ featureName, enabledComp
    return null;
    }

    // Having `displayName` is very usefull for debuging.
    FeatureFlaggedContainer.displayName = `FeatureFlaggedContainer(${ featureName })`;

    return connect((store) => { isEnabled: isFeatureEnabled(store, featureName) })(FeatureFlaggedContainer);
    2 changes: 1 addition & 1 deletion featureEnabled.js
    Original file line number Diff line number Diff line change
    @@ -1,6 +1,6 @@
    import createFeatureFlaggedContainer from './createFeatureFlaggedContainer'

    // decorator for "Page" components
    // Decorator for "Page" components.
    // usage: enabledFeature('unicorns')(UnicornsPage);
    export defualt function enabledFeature(featureName) {
    return (Component) => {
    21 changes: 9 additions & 12 deletions features.js
    Original file line number Diff line number Diff line change
    @@ -1,21 +1,18 @@
    const RECEIVE_FEATURES = 'features/receive';
    // This is quite simple reducer, containing only an array of features.
    // You can attach this data to a `currentUser` or similar reducer.

    export default featuresReducer(state, { type, payload }) {
    if (typeof state === 'undefined') {
    return [];
    }
    // `BOOTSTAP` is global action, which contains the initial data for a page
    // Features access usually don't change during user usage of a page
    const BOOTSTAP = 'features/receive';

    if (type === RECEIVE_FEATURES) {
    return payload.features;
    export default featuresReducer(state, { type, payload }) {
    if (type === BOOTSTAP) {
    return payload.features || [];
    }

    return state;
    return state || [];
    }

    export function isFeatureEnabled(features, featureName) {
    return features.indexOf(featureName) !== -1;
    }

    export function receiveFeature(features) {
    return { type: RECEIVE_FEATURES, payload: { features } };
    }
    3 changes: 3 additions & 0 deletions reducers.js
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,4 @@
    // This is your main reducer.js file
    import { combineReducers } from 'redux';

    export features, { isFeatureEnabled as isFeatureEnabledSelector } from './features';
    @@ -8,6 +9,8 @@ export default combineReducers({
    // ...other reducers
    });

    // This is the important part, access to `features` reducer should only happens via this selector.
    // Then you can always change where/how the features are stored.
    export isFeatureEnabled({ features }, featureName) {
    return isFeatureEnabledSelector(features, featureName);
    }
  2. @RStankov RStankov revised this gist Jan 5, 2017. No changes.
  3. @RStankov RStankov created this gist Jan 5, 2017.
    12 changes: 12 additions & 0 deletions EnabledFeature.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,12 @@
    import { connect } from 'react-redux';
    import { isFeatureEnabled } from './reducers'

    function EnabledFeature({ isEnabled, children }) {
    if (isEnabled) {
    return children;
    }

    return null;
    }

    export default connect((store, { name }) => { isEnabled: isFeatureEnabled(store, name) })(EnabledFeature);
    20 changes: 20 additions & 0 deletions createFeatureFlaggedContainer.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,20 @@
    import React from 'react';
    import { connect } from 'react-redux';
    import { isFeatureEnabled } from './reducers'

    export default function createFeatureFlaggedContainer({ featureName, enabledComponent, disabledComponent }) {
    function FeatureFlaggedContainer({ isEnabled, ...props }) {
    const Component = isEnabled ? enabledComponent : disabledComponent;

    if (Component) {
    return <Component ..props />;
    }

    // `disabledComponent` is optional property
    return null;
    }

    FeatureFlaggedContainer.displayName = `FeatureFlaggedContainer(${ featureName })`;

    return connect((store) => { isEnabled: isFeatureEnabled(store, featureName) })(FeatureFlaggedContainer);
    }
    13 changes: 13 additions & 0 deletions featureEnabled.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,13 @@
    import createFeatureFlaggedContainer from './createFeatureFlaggedContainer'

    // decorator for "Page" components
    // usage: enabledFeature('unicorns')(UnicornsPage);
    export defualt function enabledFeature(featureName) {
    return (Component) => {
    return createFeatureFlaggedContainer({
    featureName,
    enabledComponent: Component,
    disabledComponent: PageNotFound, // 404 page or something similar
    });
    };
    };
    21 changes: 21 additions & 0 deletions features.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,21 @@
    const RECEIVE_FEATURES = 'features/receive';

    export default featuresReducer(state, { type, payload }) {
    if (typeof state === 'undefined') {
    return [];
    }

    if (type === RECEIVE_FEATURES) {
    return payload.features;
    }

    return state;
    }

    export function isFeatureEnabled(features, featureName) {
    return features.indexOf(featureName) !== -1;
    }

    export function receiveFeature(features) {
    return { type: RECEIVE_FEATURES, payload: { features } };
    }
    13 changes: 13 additions & 0 deletions reducers.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,13 @@
    import { combineReducers } from 'redux';

    export features, { isFeatureEnabled as isFeatureEnabledSelector } from './features';
    // ...other reducers

    export default combineReducers({
    features,
    // ...other reducers
    });

    export isFeatureEnabled({ features }, featureName) {
    return isFeatureEnabledSelector(features, featureName);
    }