RelayUtils.js

October 3, 2016 ยท View on GitHub

// @flow

import React from 'react'; import { ActivityIndicator, Text, TouchableOpacity, View, } from 'react-native'; import Relay from 'react-relay';

type Variables = {[name: string]: mixed};

type Config = { queries: {[name: string]: any}; queriesParams?: ?(props: Object) => Object; fragments: {[name: string]: any}; initialVariables?: Variables; prepareVariables?: (prevVariables: Variables, route: any) => Variables; forceFetch?: bool; onReadyStateChange?: (readyState: any) => void; renderFetched?: ( props: Object, fetchState: { done: bool; stale: bool } ) => ?ReactElement; renderLoading?: () => ?ReactElement; renderFailure?: (error: Error, retry: ?() => void) => ?ReactElement; };

// TODO: Make proper loading / failure components. const LoadingView = () => ( <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}> );

const FailureView = ({ error, retry }) => ( <View style={{ paddingTop: 46, alignItems: 'center' }}> Error {error.message} Try again );

export function createRenderer( Component: ReactClass<>, config: Config ): ReactClass<> { return createRendererInternal(Component, { forceFetch: true, renderLoading: () => , renderFailure: (error, retry) => , ...config, }); }

function createRendererInternal( Component: ReactClass<>, config: Config ): ReactClass<> { const { queries, queriesParams, forceFetch, renderFetched, renderLoading, renderFailure, onReadyStateChange, fragments, initialVariables, prepareVariables, } = config;

const RelayComponent = Relay.createContainer(Component, { fragments, initialVariables, prepareVariables, });

class RelayRendererWrapper extends React.Component { state = { queryConfig: this._computeQueryConfig(this.props), };

render() {
  return (
    <Relay.Renderer
      Container={RelayComponent}
      forceFetch={forceFetch || false}
      onReadyStateChange={onReadyStateChange}
      queryConfig={this.state.queryConfig}
      environment={Relay.Store}
      render={({ done, error, props, retry, stale }) => {
        if (error) {
          if (renderFailure) {
            return renderFailure(error, retry);
          }
        } else if (props) {
          if (renderFetched) {
            return renderFetched({ ...this.props, ...props }, { done, stale });
          } else {
            return <RelayComponent {...this.props} {...props} />;
          }
        } else if (renderLoading) {
          return renderLoading();
        }
        return undefined;
      }}
    />
  );
}

componentWillReceiveProps(nextProps: Object) {
  if (this.props.routeParams !== nextProps.routeParams) {
    this.setState({
      queryConfig: this._computeQueryConfig(nextProps),
    });
  }
}

_computeQueryConfig(props: Object) {
  const params = queriesParams ? queriesParams(props) : {};
  const queryConfig = {
    name: `relay-route-${RelayComponent.displayName}`,
    queries: { ...queries },
    params,
  };

  return queryConfig;
}

}

return RelayRendererWrapper; }