Skip to content

Instantly share code, notes, and snippets.

@nodkz
Last active June 29, 2017 01:30
Show Gist options
  • Save nodkz/03f28aaa1b66195b517ecf06e92487bf to your computer and use it in GitHub Desktop.
Save nodkz/03f28aaa1b66195b517ecf06e92487bf to your computer and use it in GitHub Desktop.
relayStore with `reset` and simplified `mutate` methods
let relayStore;
function relayCreateStore() {
const env = new Relay.Environment();
env.injectNetworkLayer(new Relay.DefaultNetworkLayer('/graphql'));
if (__DEV__) {
RelayNetworkDebug.init(env);
}
env.reset = () => relayCreateStore();
env.mutate = ({
query,
variables,
collisionKey,
configs,
onSuccess,
onError,
onEnd,
onStart,
optimisticQuery,
optimisticResponse,
optimisticConfigs,
}) => {
// see docs https://facebook.github.io/relay/docs/api-reference-relay-graphql-mutation.html#content
let vars;
if (!variables) {
vars = undefined;
} else {
if (variables.input) { // eslint-disable-line
vars = variables;
} else {
vars = { input: variables };
}
}
if (onStart) {
onStart();
}
let collisionKeyComputed;
if (collisionKey) {
collisionKeyComputed = collisionKey;
} else if (variables) {
// if _id provided, then take it as collision key
if (variables._id) {
collisionKeyComputed = variables._id;
} else if (variables.record && variables.record._id) {
collisionKeyComputed = variables.record._id;
}
}
const mutation = new Relay.GraphQLMutation(
query,
vars,
null, // I don't use file upload, cause upload by signed url directly to S3
relayStore,
{
onFailure: (transaction) => {
if (onError) onError(transaction);
if (onEnd) onEnd();
},
onSuccess: (response) => {
if (onSuccess) onSuccess(response);
if (onEnd) onEnd();
},
},
collisionKeyComputed
);
if (optimisticResponse) {
mutation.applyOptimistic(
optimisticQuery || query, // if optimisticQuery not provided, then take query
optimisticResponse,
optimisticConfigs || configs,
);
}
// we can get transaction here but no need, cause callbacks already defined in constructor
const transaction = mutation.commit(configs);
return mutation;
};
relayStore = env;
return env;
}
relayCreateStore();
export default relayStore;
@nodkz
Copy link
Author

nodkz commented Mar 10, 2017

From issue facebook/relay#1046 (comment)

Closing this due new Mutation API which does not contain FatQuery and perfectly works with additional variables:

I highly recommend migrating to new mutation API. It allows writing mutation inside your React component (avoid creating Mutation files). And in many cases do not provide CONFIGS for updating data in the Relay store. No more fatigue for me with Relay Mutations.

Of course, you may make API better by writing your own wrapper above Relay.GraphQLMutation.
So code in your React component may become like this (example with an additional variable in delete method):

class Order extends Component {
  // ...

  create(formState) {
    relayStore.mutate({
      query: Relay.QL`mutation {
        orderCreate(input: $input) {
          recordId
          record {
            email
            id
          }
          orderConnection {
            ${List.getFragment('orderConnection')}
          }
        }
      }`,
      // variables: {
      //   input {
      //     record: minimize(formState.getValue()),
      //   }
      // },
      // short `variables` definition due autowrapping with `input` https://gist.github.com/nodkz/03f28aaa1b66195b517ecf06e92487bf#file-relaystore-js-L24-L32
      variables: {
        record: minimize(formState.getValue()),
      },
      onSuccess: (res) => {
        browserHistory.push({
          pathname: `/orders/${res.orderCreate.recordId}`,
        });
      },
      onError: (transaction) => {
        console.log('mutation onFailure', transaction);
      },
      onStart: () => {
        this.setState({ isSaving: true });
      },
      onEnd: () => {
        this.setState({ isSaving: false });
      },
    });
  }

  changeStatus(status, cb) {
    relayStore.mutate({
      query: Relay.QL`mutation {
        orderUpdate(input: $input) {
          record {
            status
            id
          }
        }
      }`,
      variables: {
        record: {
          _id: this.props.order._id,
          status,
        },
      },
      optimisticResponse: {
        record: {
          id: this.props.order.id,
          status: 'updating...',
        },
      },
      onSuccess: () => {
        this.setState({
          isSaved: true,
        });
        if (cb) cb();
      },
      onError: (transaction) => {
        console.log(transaction.getError());
        const e = transaction.getError();
        const errMsg = e ? e.message.toString() : null;
        this.setState({ errMsg });
      },
      onStart: () => {
        this.setState({
          isSaved: false,
          isSaving: true,
          errMsg: null,
        });
      },
      onEnd: () => {
        this.setState({
          isSaving: false,
        });
      },
    });
  }

  delete() {
    relayStore.mutate({
      query: Relay.QL`mutation {
        orderRemove(input: $input) {
          nodeId
          viewer {
            orderConnection(first: $first) {
              edges {
                node {
                  _id
                }
              }
            }
          }
        }
      }`,
      variables: {
        input: {
          _id: this.props.order._id,
        },
        first: 666,
      },
      onSuccess: () => {
        browserHistory.goLevelUp();
      },
      onError: (transaction) => {
        alert(transaction.getError());
      },
      onStart: () => {
        this.setState({ isSaving: true });
      },
      onEnd: () => {
        this.setState({ isSaving: false });
      },
    });
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment