Skip to content

Instantly share code, notes, and snippets.

@johnrjj
Created February 20, 2019 19:42
Show Gist options
  • Select an option

  • Save johnrjj/1fa53b6d70ad2955de4958193cc787a0 to your computer and use it in GitHub Desktop.

Select an option

Save johnrjj/1fa53b6d70ad2955de4958193cc787a0 to your computer and use it in GitHub Desktop.

Revisions

  1. johnrjj created this gist Feb 20, 2019.
    25 changes: 25 additions & 0 deletions App.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,25 @@
    import React, { Component } from 'react';
    import { Experiment } from './experiment/Experiment';
    import { Case } from './experiment/Case';

    class App extends Component {
    render() {
    return (
    <div className="App">
    <Experiment>
    <Case when={(experimentMetadata) => experimentMetadata.foo === 'bar'}>
    <button>swag button</button>
    </Case>
    <Case when={(experimentMetadata) => experimentMetadata.foo === 'baz'}>
    <button>super swag button</button>
    </Case>
    <Case when={(experimentMetadata) => experimentMetadata.foo === 'bat'}>
    <button>the swaggiest</button>
    </Case>
    </Experiment>
    </div>
    );
    }
    }

    export default App;
    20 changes: 20 additions & 0 deletions Case.tsx
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,20 @@
    import ReactDOM from 'react-dom';
    import React, { useEffect, useRef } from 'react';
    import { useExperiment } from './Experiment';

    const Case = ({ when, children }: any) => {
    const experiment = useExperiment();
    const { data } = experiment;
    const shouldShow = when(data);

    if (!shouldShow) {
    return null;
    }
    return (
    <React.Fragment>
    {children}
    </React.Fragment>
    ) as any;
    };

    export { Case };
    63 changes: 63 additions & 0 deletions Experiment.tsx
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,63 @@
    import * as React from 'react';

    const uid = () =>
    `${Math.random()
    .toString(32)
    .substr(2, 8)}`;

    const Context = React.createContext<ExperimentContext>({
    cases: [],
    data: {},
    experimentId: uid(),
    registerCase: () => {},
    unregisterCase: () => {},
    });

    export interface ExperimentContext {
    cases: any;
    data: any;
    registerCase: any;
    unregisterCase: any;
    experimentId: string;
    }

    export interface NodeManagerProps {
    children: React.ReactNode;
    }

    export const Experiment: React.FC<NodeManagerProps> = ({ children }) => {
    const [cases, setCases] = React.useState<any>({});
    const [data, setData] = React.useState<any>({ foo: 'bar' });

    const experimentId = React.useRef(uid());

    const registerCase = React.useCallback<ExperimentContext['registerCase']>((component,key = uid()) => {
    return setCases(n => ({ ...n, [key]: component }));
    }, []);

    const unregisterCase = React.useCallback<ExperimentContext['unregisterCase']>(
    key => {
    setCases(n => {
    const { [key]: omitted, ...rest } = n;
    return rest;
    });
    },
    []
    );

    const context = React.useMemo(() => {
    return {
    experimentId: experimentId.current,
    cases,
    data,
    registerCase,
    unregisterCase,
    };
    }, [cases, experimentId, data, unregisterCase, experimentId]);
    return <Context.Provider value={context}>{children}</Context.Provider>;
    };

    export function useExperiment() {
    const context = React.useContext(Context);
    return context;
    }