Relay: [Modern] List not rendered correctly after having used `updater` with `requestSubscription`

Created on 23 Jun 2017  路  1Comment  路  Source: facebook/relay

I've integrated subscriptions in my app with the requestSubscription function. Subscriptions work well and the updater gets called correctly with the correct subscription payload.

The subscription is used to add a new item to a list. Here's what the subscription looks like:

NewLinkSubscription.js

const newLinkSubscription = graphql`
  subscription NewLinkSubscription {
    Link {
      mutation
      node {
        id
        description
        url
        createdAt
        postedBy {
          id
          name
        }
      }
    }
  }
`

export default (updater, onError) => {

  const subscriptionConfig = {
    subscription: newLinkSubscription,
    variables: {},
    updater,
    onError
  }

  requestSubscription(
    environment,
    subscriptionConfig
  )

}

I have a LinkList component that's rendering all the Link elements. In componentDidMount of that component, I initiate the NewLinkSubscription:

LinkList.js

class LinkList extends Component {

  componentDidMount() {
    NewLinkSubscription(
      proxyStore => {
        const createLinkField = proxyStore.getRootField('Link')
        const newLink = createLinkField.getLinkedRecord('node')
        const viewerProxy = proxyStore.get(this.props.viewer.id)
        const connection = ConnectionHandler.getConnection(viewerProxy, 'LinkList_allLinks')
        if (connection) {
          ConnectionHandler.insertEdgeAfter(connection, newLink)
        }
      },
      error => console.log(`An error occured:`, error),
    )
  }

  render() {
    console.log(`LinkList - render `, this.props.viewer.allLinks.edges)
    return (
      <div>
        {this.props.viewer.allLinks.edges.map(({node}) =>
          {
            console.log(`render node: `, node)
            return <Link key={node.id} link={node} viewer={this.props.viewer} />
          }
        )}
      </div>
    )
  }

}

export default createFragmentContainer(LinkList, graphql`
  fragment LinkList_viewer on Viewer {
    id
    ...Link_viewer
    allLinks(last: 100, orderBy: createdAt_DESC) @connection(key: "LinkList_allLinks", filters: []) {
      edges {
        node {
          ...Link_link
        }
      }
    }
  }
`)

Here's what's happening when a subscription with a new Link comes in. The updater is called correctly and it seems like the new node gets inserted into the connection correctly (at least ConnectionHandler.insertEdgeAfter(connection, newLink) is called).

This triggers a rerender of the component. When I put a debug render to inspect the data (props.viewer.allLinks.edges), I can see that a new node indeed was added to the connection - so the list actually does contain one more item now! However, the problem is that this new node is actually undefined which causes the app to crash!

image

Does anyone spot what I'm missing here?

Most helpful comment

I was able to fix the issue by using ConnectionHandler.createEdge(). This is how the updater is implemented now:

NewLinkSubscription(
  proxyStore => {
    const linkField = proxyStore.getRootField('Link')
    const newLink = linkField.getLinkedRecord('node')
    const viewerProxy = proxyStore.get(this.props.viewer.id)
    const connection = ConnectionHandler.getConnection(viewerProxy, 'LinkList_allLinks', {
      last: 100,
      orderBy: 'createdAt_DESC'
    })
    if (connection) {
      const edge = ConnectionHandler.createEdge(proxyStore, connection, newLink, 'allLinks')
      ConnectionHandler.insertEdgeBefore(connection, edge)
    }
  },
  error => console.log(`An error occured:`, error),
)

>All comments

I was able to fix the issue by using ConnectionHandler.createEdge(). This is how the updater is implemented now:

NewLinkSubscription(
  proxyStore => {
    const linkField = proxyStore.getRootField('Link')
    const newLink = linkField.getLinkedRecord('node')
    const viewerProxy = proxyStore.get(this.props.viewer.id)
    const connection = ConnectionHandler.getConnection(viewerProxy, 'LinkList_allLinks', {
      last: 100,
      orderBy: 'createdAt_DESC'
    })
    if (connection) {
      const edge = ConnectionHandler.createEdge(proxyStore, connection, newLink, 'allLinks')
      ConnectionHandler.insertEdgeBefore(connection, edge)
    }
  },
  error => console.log(`An error occured:`, error),
)
Was this page helpful?
0 / 5 - 0 ratings

Related issues

amccloud picture amccloud  路  3Comments

piotrblasiak picture piotrblasiak  路  3Comments

scotmatson picture scotmatson  路  3Comments

johntran picture johntran  路  3Comments

HsuTing picture HsuTing  路  3Comments