I'm using Relay Modern for my app and am trying to update the cache after a mutation using the updater
and optimisticUpdater
but it doesn't quite work.
Basically, I have a Link
type with a votes
connection - here's the relevant part of my schema:
type Link implements Node {
createdAt: DateTime!
description: String!
id: ID!
postedBy(filter: UserFilter): User
url: String!
votes(filter: VoteFilter, orderBy: VoteOrderBy, skip: Int, after: String, before: String, first: Int, last: Int): VoteConnection
}
type Vote implements Node {
createdAt: DateTime!
id: ID!
link(filter: LinkFilter): Link!
updatedAt: DateTime!
user(filter: UserFilter): User!
}
# A connection to a list of items.
type VoteConnection {
# Information to aid in pagination.
pageInfo: PageInfo
# A list of edges.
edges: [VoteEdge]
# Count of filtered result set without considering pagination arguments
count: Int!
}
# An edge in a connection.
type VoteEdge {
# The item at the end of the edge.
node: Vote
# A cursor for use in pagination.
cursor: String
}
Here's the code for my Link
component request the votes
in a fragment:
class Link extends Component {
render() {
const userId = localStorage.getItem(GC_USER_ID)
return (
<div>
{userId && <div onClick={() => this._voteForLink()}>▲</div>}
<div>{this.props.link.description} ({this.props.link.url})</div>
<div>{this.props.link.votes.edges.length} votes | by {this.props.link.postedBy ? this.props.link.postedBy.name : 'Unknown'} {this.props.link.createdAt}</div>
</div>
)
}
_voteForLink = () => {
const userId = localStorage.getItem(GC_USER_ID)
const linkId = this.props.link.id
CreateVoteMutation(userId, linkId, this.props.viewer.id)
}
}
export default createFragmentContainer(Link, graphql`
fragment Link_viewer on Viewer {
id
}
fragment Link_link on Link {
id
description
url
createdAt
postedBy {
id
name
}
votes(last: 1000, orderBy: createdAt_DESC) @connection(key: "Link_votes", filters: []) {
edges {
node {
id
user {
id
}
}
}
}
}
`)
Finally, this is the CreateVoteMutation
with the updater
:
const mutation = graphql`
mutation CreateVoteMutation($input: CreateVoteInput!) {
createVote(input: $input) {
vote {
id
link {
id
}
user {
id
}
}
}
}
`
export default (userId, linkId, viewerId) => {
const variables = {
input: {
userId,
linkId,
clientMutationId: ""
},
}
commitMutation(
environment,
{
mutation,
variables,
updater: (proxyStore) => {
const createVoteField = proxyStore.getRootField('createVote')
const newVote = createVoteField.getLinkedRecord('vote')
const viewerProxy = proxyStore.get(viewerId)
const connection = ConnectionHandler.getConnection(viewerProxy, 'Link_votes')
// `connection` is undefined, so the `newVote` doesn't get inserted
if (connection) {
ConnectionHandler.insertEdgeAfter(connection, newVote)
}
},
onError: err => console.error(err),
},
)
}
The call to ConnectionHandler.getConnection(viewerProxy, 'Link_votes')
only returns undefined
, so the newVote
doesn't actually get inserted.
Does anyone see what I'm doing wrong?
Problem:
When you're getting your connection:
const connection = ConnectionHandler.getConnection(viewerProxy, 'Link_votes')
you're trying to get the connection 'Link_votes' on the ViewerProxy. However what you want to be doing is getting the connection on the link.
Solution:
First you would need to get the id of the link that your adding the vote to.
const linkId = newVote.getLinkedRecord('link').getValue('id');
Then you want to get the Link Proxy so that you can then get the correct connection.
const linkProxy = proxyStore.get(LinkId)
Now that you have the Link Proxy that represents the link that you wanted the connection for, you can now get that connection.
const connection = ConnectionHandler.getConnection(linkProxy, 'Link_votes')
Sweet so now you've got the connection. Which solves the issue you're having.
However there is another problem, the way you go on to add the vote is wrong first you need to create an Edge out of it, and then add the edge.
First we need to create an edge
const voteEdge = createEdge(proxyStore, connection, newVote, 'VoteEdge');
Now that we have the voteEdge we can append it to the connection.
ConnectionHandler.insertEdgeAfter(connection, voteEdge).
Now it should all work. However you probably shouldn't be using the updater function for this kind of action. You should be using the RANGE_ADD configuration https://facebook.github.io/relay/docs/mutations.html#range-add and change how your server responds to that mutation.