How to update cache with nested query

Our app is using GraphQL to query an SQL database. We have a table of Posts. Users can Like (join) a Post, which creates an item on a Join table. When we query a feed of Posts we have a subquery that grabs the Like. Our like/unlike function checks if this Like object is there in each Post and does the right Mutation. So far this has all worked correctly, but we are having issues with getting it to work optimistically.

The setup looks like this:

type User {
    id: ID
    username: String
    ...
}

type Like {
    id: ID
    userId: ID
    postId: ID
}

type Post {
    id: ID
    message: String
    image: Image
    likeItem(userID: ID): Like
}

Our Query looks like this

query GetPosts($userId: ID) {
    allPosts {
        id
        message
        image {
            id
            url
        }
        likeItem({id: $userId}) {
            id
        }
    }
}

This all works. Our question is how do we update something like this optimistically without having to refetch the whole feed? When we look at the cache for “Post:123ABC…” it has multiple “likeItem” keys.

{
...
    likeItem({}): null
    likeItem({id: "SomeUserId..."}): {__ref: "Like:123ABC..."}
...
} 

We could not get cache.writeFragment to update the correct key because the structure is not JSON (thus could not pass it to the data key). Same with cache.writeQuery. So far we have had to use refetchQueries, though it has not been very performant.

Hello! As a first thought, if a user’s “liking” of a post is a binary setting, it might be more straightforward to represent the likeItem field in your schema as a Boolean instead of an object type. Your likeItem resolver would then return true or false according to the presence or absence of a corresponding Like entity in your SQL table for that user-post duo.

This way, when optimistically adding or removing a “like” locally, you don’t need to worry about creating or removing full Like objects in your cache. Instead, you can use writeFragment or cache.modify to flip a single boolean on a Post object that is more stable.

Is that helpful, or am I misrepresenting the issue?

1 Like

Hi Stephen,

After examining the issue we determined that this is the correct behavior vis-a-vis the GraphQL spec. We really want the whole Like object instead of a boolean, or at least the ID, so we can easily destroy it if needed. We have had some luck updating this specific item using writeQuery though it become somewhat unmanageable when dealing with a feed of posts. We are using Relay style pagination (with cursors) so it quickly becomes a mess when trying to pass the right variables into writeQuery. We are instead just using refetchQueries and telling the component to re-run the query, but just against the cache.