lvarayut / relay-fullstack

:point_up::running: Modern Relay Starter Kit - Integrated with Relay, GraphQL, Express, ES6/ES7, JSX, Webpack, Babel, Material Design Lite, and PostCSS
https://lvarayut.github.io/relay-fullstack/
MIT License
985 stars 126 forks source link

New Relay mutation #64

Closed Neitsch closed 7 years ago

Neitsch commented 7 years ago

Note, that right now the new GraphQLMutation is not yet in RelayPublic.js, so it must be imported by its relative path. I really like the syntax, especially adding optimistic updates was super easy. I was not able to find any production coding examples, so I'm not sure if it would be better to put everything in a class. Relay 2 is supposed to be released very soon (https://github.com/facebook/relay/blob/master/meta/meeting-notes/2017-01-24-team-sync.md), but for now this should stay on the canary branch. Feel free to suggest changes.

ncrmro commented 7 years ago

Awesome work! Haven't tested it but seems like a lot of logic to put into a component.

What if we still imported the mutation and did something like this. Sort of hackish but the idea I think being the mutation logic is reusable in maybe a react native project. Haven't tested either.

AddFeatureComponent.js

import AddFeatureMutation from './AddFeatureMutation';

...
  addFeature = () => {
    const value = this.state.form.dropdown.value;
    if (value === 'none') {
      return;
    }

    AddFeatureMutation(inputData, value);
  };
...

AddFeatureMutation.js

//export a function that accepts the input data and value. Input data used for optimistic response
export default (inputData, value) => {
  const query =
      Relay.QL`mutation {
          addFeature {
              featureEdge {
                  __typename
                  node {
                      name
                      id
                      description
                      url
                  }
              }
          }
      }`;
  const variables = {
    input: {
      ...inputData[value]
    }
  };
  const mutation = new RelayGraphQLMutation(
    query,
    variables,
    null, // no files
    Relay.Store,
    null, // callback not necessary
    value // value is collision key
  );

  const optimisticQuery =
      Relay.QL`mutation {
          addFeature {
              featureEdge {
                  node {
                      name
                      description
                      url
                  }
              }
          }
      }`;
  const optimisticResponse = {
    featureEdge: {
      node: {
        ...inputData[value]
      }
    }
  };
  const config = [{
    type: 'RANGE_ADD',
    parentName: 'viewer',
    parentID: this.props.viewer.id,
    connectionName: 'features',
    edgeName: 'featureEdge',
    rangeBehaviors: {
      '': 'append'
    }
  }];
  mutation.applyOptimistic(optimisticQuery, optimisticResponse, config);
  mutation.commit(config);
}
Neitsch commented 7 years ago

It's flowtype type checking: Question mark means it's optional, array is built-in flowtype and RelayMutationConfig is declared by react/relay

56

lvarayut commented 7 years ago

@Neitsch, thanks for your awesome work! Could you also apply these changes to the master branch? My initial thought of canary was that it will contain optional features, such as Flow type and databases. These optional features will be choices for developers to choose whiling generating our project using Yeoman generator, canary branch should make our yeoman branch cleaner and easier to manage. At the end of the day, master branch is a subset of canary branch. We normally apply any general changes to master branch, and then merge them into canary.

However, master and canary are sometimes out of sync. We need to apply any changes to both branches, which's kind of messy. If anyone has any better idea, please do let me know!

Neitsch commented 7 years ago

Oh okay, I thought we PR to canary and if a feature is stable it is merged into master. I'll PR this to master once Relay 2 is officially released 😄

I'm looking into Yeoman subgenerators. It should be possible to just have master and use this composeWith functionality. This might be a major undertaking though.