Relay: How to avoid Dup Records when executing Create Mutation Commits that Insert New Edges into Connections

Created on 8 May 2017  路  5Comments  路  Source: facebook/relay

Having trouble implementing a simple Document Component that adds a document and updates a connection relation with Application.documents edges. The Create works fine, but the Updater keeps adding the LinkedRecord reference to the same Edge every time I run InsertEdgeAfter on the Application.documents Connection. This causes duplicate records since it keeps updating the old Edge records by reference. I'm hoping I don't have to destroy the Component to create a separate reference for the Create Edge LinkedRecord. How do we add multiple edges to Connections if we always receive the same referenced Edge?

Here is the mutation to create a document, it returns an associated Application.id as well as the expected edge.

const mutation = graphql
  mutation CreateDocumentMutation($input: CreateDocumentInput!) {
    createDocument(input: $input) {
      document {
        id
        data
      }
      edge {
        __typename
        cursor
        node {
          id
          application{
            id
          }
          data
        }
      }
      application {
        id        
      }
    }
  }

Here is my updater method that gets the payload, finds the Edge, then uses the application proxy to get the Connection to insert the Edge into. The problem is the Edge is a linked record and every time I run a commit on this create it keeps updating the Edge reference and incrementing pointers to the latest Edge value.

updater: (store) => {
        const payload = store.getRootField('createDocument')
        const newEdge = payload.getLinkedRecord('edge')
        const proxy = store.get(application.id)
        const conn = ConnectionHandler.getConnection(proxy, 'application_documents')        
        ConnectionHandler.insertEdgeAfter(conn, newEdge)
      }

My connection is simply just a list of the documents for this application. After I insert each document, the list starts creating duplicates simply because the references all point to the last Edge created. The GraphQL data storage is fine, but my local update is failing due to this issue.

Application.documents = [
11111, <- created in an earlier session
2222, <- created in an earlier session
12345, <- created in the current session
12345, <- created in the current session
12345, <- created in the current session, keeps repeating as I run the commit trigger
]

Most helpful comment

I had a similar problem and setup. I was able to resolve the issue by pulling the 'node' out of my edge, creating a new edge with ConnectionHandler.createEdge, then calling insertEdgeAfter with the newly created edge.

function commit(channelID, kind) {
  const variables = {
    input: {
      channelID,
      kind,
    }
  }

  commitMutation(
    environment,
    {
      mutation,
      variables,
      updater: (store) => {
        const payload = store.getRootField('createInvitation');
        const node = payload.getLinkedRecord('invitationEdge').getLinkedRecord('node');
        const channelProxy = store.get(channelID);
        const conn = ConnectionHandler.getConnection(
          channelProxy,
          'ChannelView_invitationConnection',
        );
        const newEdge = ConnectionHandler.createEdge(
          store,
          conn,
          node,
          "InvitationEdge"
        )
        ConnectionHandler.insertEdgeAfter(conn, newEdge);
    }
  })
}

Not entirely sure why it didn't work before, but seems to work when I create the new edge. I think the issue could be related to my variables not changing between mutation commits?

All 5 comments

I had a similar problem and setup. I was able to resolve the issue by pulling the 'node' out of my edge, creating a new edge with ConnectionHandler.createEdge, then calling insertEdgeAfter with the newly created edge.

function commit(channelID, kind) {
  const variables = {
    input: {
      channelID,
      kind,
    }
  }

  commitMutation(
    environment,
    {
      mutation,
      variables,
      updater: (store) => {
        const payload = store.getRootField('createInvitation');
        const node = payload.getLinkedRecord('invitationEdge').getLinkedRecord('node');
        const channelProxy = store.get(channelID);
        const conn = ConnectionHandler.getConnection(
          channelProxy,
          'ChannelView_invitationConnection',
        );
        const newEdge = ConnectionHandler.createEdge(
          store,
          conn,
          node,
          "InvitationEdge"
        )
        ConnectionHandler.insertEdgeAfter(conn, newEdge);
    }
  })
}

Not entirely sure why it didn't work before, but seems to work when I create the new edge. I think the issue could be related to my variables not changing between mutation commits?

Thanks for reporting this. It's a known issue where mutations with the same variables end up having the same ids for some records (those that don't have their own id, including edges). @amozoss's suggestion of using createEdge() is a solid workaround.

@josephsavona I this need to create my own updater and cannot relay on RANGE_ADD for the moment?

Hey, I solved this by removing RANGE_ADD on configs, it's either you choose from updater or RANGE_ADD

use updater or config

tks

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jstejada picture jstejada  路  3Comments

piotrblasiak picture piotrblasiak  路  3Comments

scotmatson picture scotmatson  路  3Comments

sibelius picture sibelius  路  3Comments

fedbalves picture fedbalves  路  3Comments