Relay: [Modern] RANGE_ADD Mutation with configs

Created on 18 Oct 2017  路  14Comments  路  Source: facebook/relay

Hi, The docu here: https://facebook.github.io/relay/docs/mutations.html#range-add
suggests to use configs to configure the store updating mechanism.

Unfortunately it is unclear to me what the parentId: 'shipId' references to and where the connectionKey is coming from.

Let's suppose I have the following query:

graphql`query AppQuery($rows: Int!) {
        allChatMessages(first: $rows) {
            totalCount
            edges {
                node {
                    message
                    username
                }
             }
        }
    }`

I suppose my configs would look like:

const configs = [{
    type: 'RANGE_ADD',
    parentID: 'id',
    connectionInfo: [{
      key: 'allChatMessages',
      rangeBehavior: 'append',
    }],
    edgeName: 'chatMessageEdge',
  }];

with a mutation like

    mutation createChatMessageMutation($input: CreateChatMessageInput!) {
        createChatMessage(input: $input) {
            chatMessage {
                username
                message
                updated
            }
            chatMessageEdge {
                node {
                    id
                }
            }
        }
    }

is this correct?

Most helpful comment

if you are still using viewer, the viewer.id is the parentId of your connection

if you are not using viewer and just have a connection in root, your parentId is client:root:

/**
 * An id used for the root of the graph, corresponding to the "Query" type.
 * Conceptually, root fields in queries can be viewed as normal fields on a
 * synthesized root record.
 */
const ROOT_ID = 'client:root';

check in the code: https://github.com/facebook/relay/blob/1d72862fa620a9db69d6219d5aa562054d9b93c7/packages/react-relay/classic/store/RelayStoreConstants.js#L18

this const should be exported in react-relay I guess, so it makes easier and less error prone if relay decides to change this anytime

All 14 comments

I think you need to annotate your connection and refer to that in the config. Like this:

graphql`query AppQuery($rows: Int!) {
        allChatMessages(first: $rows) @connection(key: "AppQuery_allChatMessages") {
            totalCount
            edges {
                node {
                    message
                    username
                }
             }
        }
    }`

...and then refer to AppQuery_allChatMessages as the connection key in your config.

However, I have no clue about the parentID when it has no parent. Looking at the source it looks like it is required: https://github.com/facebook/relay/blob/6d87a701de69ce1e271895ff689ddbda2b39b4c2/packages/relay-runtime/mutations/setRelayModernMutationConfigs.js#L114-L122

Maybe someone from the Relay team can clarify how this works with connections not nested under a parent but on the top level of the query...?

My query field has an id field which I now pass. And I added the connection annotation from your suggestion. But my MessagesList component does not automatically update after the graphql response :(

With a lot of searching in code I found out that, altough my graphql api returns query as parent-id, my relay store used client:root as parent-id.
Optimistic Update only worked with a updater function. You can see the different usages in Delete and Create Mutations at: https://github.com/valorize/sm-chat/tree/master/src/mutations

@sibelius would this be a leftover issue from the days where viewer was a "required" root field? and so what we are seeing is that RANGE_ADD operations on connections at the root, fail with the configs due to this name mismatch. @valorize I'd be curious if you nested that connection under viewer, and used viewer as the parentID, if the configs would work for you.

if you are still using viewer, the viewer.id is the parentId of your connection

if you are not using viewer and just have a connection in root, your parentId is client:root:

/**
 * An id used for the root of the graph, corresponding to the "Query" type.
 * Conceptually, root fields in queries can be viewed as normal fields on a
 * synthesized root record.
 */
const ROOT_ID = 'client:root';

check in the code: https://github.com/facebook/relay/blob/1d72862fa620a9db69d6219d5aa562054d9b93c7/packages/react-relay/classic/store/RelayStoreConstants.js#L18

this const should be exported in react-relay I guess, so it makes easier and less error prone if relay decides to change this anytime

@sibelius That's not quite right. For RANGE_ADD, I think you need to generate the config dynamically, and use the Relay node ID for the parent node.

If you're using viewer, client:root:viewer seems to work.

Hi folks, @sibelius, not sure if this thread is dead but I could sure use some help here.
My connection isn't a root query, but one level deeper, as a todos field in a TodoList GraphQLObjectType, which is the type of the root query todos.
So, the query would look something like:

query {
  todos { #TodoList query 
    id, #id of TodoList
    todos(first: 10) { #TodoConnection
      edges {
        node {
          id,
          title,
          created,
          last_updated,
          complete,
          due
        }
      }
    }
  }
}

Would the parentID become the id field of the TodoList? Trying that doesn't yield success. Any help would be much appreciated. I have updated my query to use the @connection annotation.

todos inside todos is kind of weird

try to debug using relay devtools, to understand the shape of your environment

the parent of todos connection is todos.id

try to use @connection(key: "componentName_todos", filters: [])

also create a repo to reproduce this issue

@sibelius, I have a repo I'm working in that's causing this issue. I'm not working with todos in it, but skits, pre-conceived conversations between bots. The repo contains both my GraphQL schemas and the client code which has the relay stuff: https://github.com/elonybear/social-attitudes.

Here's the mutation: https://github.com/elonybear/social-attitudes/blob/master/src/components/content/panes/messaging/create/CreateSkitMutation.js.
And here's the list of skits: https://github.com/elonybear/social-attitudes/blob/master/src/components/content/panes/messaging/list/SkitList.js

As of now, I've attempted to make the SkitConnection the root query, which proved a no-go. Also, I've attempted to make the key in the @connection annotation empty, but relay-compiler throws an error with that.

why parentID is fixed? pass it as a variables

why don't u try to use updater instea of getConfigs?

check this https://medium.com/entria/wrangling-the-client-store-with-the-relay-modern-updater-function-5c32149a71ac

Yeah, I noticed that after I pushed it, just pushed a fix. Hmm, okay. That's more manually telling the store to make these updates?

we can chat more about it here https://graphql-slack.herokuapp.com/ on #relay channel

updater is fine grained, easier to grasp

@kassens should we expose ROOT_ID in relay public api?

Was this page helpful?
0 / 5 - 0 ratings