2
votes

I learn GraphQL with howtographql.com, but when use mutation for vote the UI doesn't update. I use readQuery and writeQuery on store, after search I test use readQuery and writeQuery on client but doesn't work again.

Package use and version :
├─ [email protected]
├─ [email protected]
├─ [email protected]
├─ [email protected]
├─ [email protected]
├─ [email protected]
├─ [email protected]
├─ [email protected]
├─ [email protected]
├─ [email protected]
├─ [email protected]

LinkList.js

import React, { Component } from 'react';
import Link from './Link';
import { Query } from 'react-apollo';
import gql from 'graphql-tag';

export const FEED_QUERY = gql`
    {
        feed {
            links {
                id
                createdAt
                url
                description
                postedBy {
                    id
                    name
                }
                votes {
                    id
                    user {
                        id
                    }
                }
            }
        }
    }
`

class LinkList extends Component {
    _updateCacheAfterVote = (store, createVote, linkId) => {
        const data = store.readQuery({ query: FEED_QUERY })

        const votedLink = data.feed.links.find(link => link.id === linkId)
        votedLink.votes = createVote.link.votes

        store.writeQuery({ query: FEED_QUERY, data })
    }
    render() { 
        return (
            <Query query={FEED_QUERY}>
                {({ loading, error, data }) => {
                    if (loading) return <div>Fetching</div>
                     if (error) return <div>Error</div>

                    const linksToRender = data.feed.links

                    return (
                        <div>
                            {linksToRender.map((link, index) => (
                                <Link
                                    key={link.id} 
                                    link={link} 
                                    index={index} 
                                    updateStoreAfterVote={this._updateCacheAfterVote}
                                />
                            ))}
                        </div>
                    )
                }}
            </Query>
        )
    }
}

export default LinkList

Link.js

import React, { Component } from 'react'
import { AUTH_TOKEN } from '../constants'
import { timeDifferenceForDate } from '../utils';
import { Mutation } from 'react-apollo';
import gql from 'graphql-tag';

const VOTE_MUTATION = gql`
    mutation VoteMutation($linkId: ID!) {
        vote(linkId: $linkId) {
            id
            link {
                votes {
                    id
                    user {
                        id
                    }
                }
            }
            user {
                id
            }
        }
    }
`

class Link extends Component {
    render() {
        const authToken = localStorage.getItem(AUTH_TOKEN)
        return (
            <div className="flex mt2 items-start">
                <div className="flex items-center">
                    <span className="gray">{this.props.index + 1}</span>
                    {authToken && (
                        <Mutation
                            mutation={VOTE_MUTATION}
                            variables={{ linkId: this.props.link.id }}
                            update={(store, { data: { vote } }) =>
                                this.props.updateStoreAfterVote(store, vote, this.props.link.id)
                            }
                        >
                            {voteMutation => (
                                <div className="ml1 gray fl1 pointer" onClick={voteMutation}>
                                    ▲
                                </div>
                            )}
                        </Mutation>
                    )}
                </div>
                <div className="ml1">
                    <div>
                        {this.props.link.description} ({this.props.link.url})
                    </div>
                    <div className="f6 lh-copy gray">
                        {this.props.link.votes.length} votes | by{' '}
                        {this.props.link.postedBy
                            ? this.props.link.postedBy.name
                            : 'Unknown'}{' '}
                        {timeDifferenceForDate(this.props.link.createdAt)}
                    </div>
                </div>
            </div>
        )
    }
}

export default Link
1
Is there any error or warning shown in the console after the mutation runs?Daniel Rearden
No, the mutation work correctly without error but doesn't update UIPepeCitron

1 Answers

3
votes

I change _updateCacheAfterVote function like this and it's work

_updateCacheAfterVote = (store, createVote, linkId) => {
    const data = store.readQuery({ query: FEED_QUERY })
    data.feed.links.find(link => link.id === linkId).votes.push(createVote)
    store.writeQuery({ query: FEED_QUERY, data })
}