Search code examples
reactjsfluxreactjs-fluxgraphqlrelayjs

How to fire Flux actions for RelayMutations


In other words, How can I get local state (flux stores such as ModalStore, HistoryStore etc) to update upon relay mutation. Only solution I could find is to use callbacks to fire flux actions. However this becomes very redundant and dangerous, since I have to fire an action every time that mutation is used and, that piece of code depends on the shape of the mutation payload. I have a feeling that there is a much better solution that I'm not aware of.


Solution

  • Before heading off to the server, every mutation goes through the sendMutation method of the network layer. One solution could be to intercept mutations there, then fire optimistic, commit, and rollback Flux actions.

    Presuming that for every single Relay mutation named FooMutation you have three corresponding Flux actions called RelayMutationActions.(doOptimistic|commit|rollback)FooMutation, something like this might work:

    var myNetworkLayer = {
      ...Relay.DefaultNetworkLayer,
      sendMutation(mutationRequest) {
        // Pluck the mutation from the outgoing request
        const mutation = mutationRequest.getMutation();
        const mutationName = mutation.getName();
        const mutationPayload = mutation.getVariables().input;
    
        // Fire an optimistic Flux action immediately
        RelayMutationActions[`doOptimistic${mutationName}`](mutationPayload);
    
        // Pass the request on to the default network layer implementation
        return Relay.DefaultNetworkLayer.sendMutation(mutationRequest)
          .then(payload =>
            if (payload.hasOwnProperty('errors')) {
              // If there was an error, fire a new rollback Flux action
              RelayMutationActions[`rollback${mutationName}`](payload);
            } else {
              // Otherwise fire a Flux action that commits the transaction
              RelayMutationActions[`commit${mutationName}`](payload);
            }
          );
      },
    };
    Relay.injectNetworkLayer(myNetworkLayer);