sibelius
2/22/2017 - 8:52 PM

redux-relay

redux-relay

import React from 'react';
import { container } from 'redux-relay';



@container({
  variablesFromState: (state) => ({myVariable: state.myState})
  fragments: {
    Relay.QL`
      viewer {
        myFunc($myVariable) {
          foo,
          bar
        }
      }
    `
  } 
});
class Container extends React.Component {
  render() {
    const { viewer } = this.props;
    ....
  }
}

export default Container;
import { Provider } from 'redux-relay';
import Relay from 'react-relay';
import ReactDOM from 'react-dom';
import configureStore from './store';
import Container from './Container';
import route from './route';

const store = configureStore();

ReactDOM.render(
  <Provider store={store}>
    <Relay.RootContainer route={route} Component={Container} />
  </Provider>
);
import Relay from 'react-relay';
import React from 'react';
import {Provider as ReactReduxProvider } from 'react-redux';

let store;

function setStore(value) {
  store = value;
}

const containerProperties = {
  'getFragmentNames': true,
  'getQueryNames': true,
  'hasFragment': true,
  'hasVariable': true,
  'getFragment': true,
  'getQuery': true,
  'contextTypes': false,
  'displayName': false,
  'moduleName': false
};

function createLazyContainer(Container, variablesFromState, fragments) {
  let relayContainer;
  const getRelayContainer = () => {
    if (!relayContainer) {
      const {forceFetch, ...initialVariables} = variablesFromState(store.getState()); //eslint-disable-line no-unused-vars
      relayContainer = Relay.createContainer(Container, { initialVariables, fragments });
    }
    return relayContainer;           
  };

  const lazyContainer = (props, context) => {
    const Container = getRelayContainer();
    return new Container(props, context);
  };
  
  for (let property of Object.keys(containerProperties)) {
    const isFunction = containerProperties[property];
    if (isFunction) {
      Object.defineProperty(lazyContainer, property, {
        value: function (...args) {
          const container = getRelayContainer();
          return container[property](...args);
        },
        enumerable: true,
        configureable: true,
        writable: true
      });
    } else {
      Object.defineProperty(lazyContainer, property, {
        get: () => getRelayContainer()[property],
        set: (val) => getRelayContainer()[property] = val,
        enumerable: true,
        configureable: true
      });
    }
  }
  
 
  return lazyContainer;
}

export function container({variablesFromState, fragments}) {
  return function (Component) {
    
    if (variablesFromState) {
      class Container extends React.Component {
      
        static displayName = `ReduxRelay(${Component.displayName || Component.name})`

        componentDidMount() {
          this._subscription = store.subscribe(() => {
            const { forceFetch, ...variables } = variablesFromState(store.getState());
            if (forceFetch) {
              this.props.relay.forceFetch(variables);
            } else {
              this.props.relay.setVariables(variables);
            }
          });
        }

        componentWillUnmount() {
          this._subscription.dispose();
        }

        render() {
          return <Component {...this.props} />;
        }
      }
                   
      return createLazyContainer(Container, variablesFromState, fragments);
    } else {
      return Relay.createContainer(Component, { fragments });                  
    }
  };
}
      
export const Provider = ({store, ...props}) => {
  setStore(store);
  return <ReactReduxProvider store={store} {...props} />;
};