Search code examples
reactjsgraphqlapollo

useQuery not returning up to date data


  • i have a homepage (/home) with a list of products as cards (retrieved via useQuery) each of which has an upvote button
  • when I click upvote, i trigger a mutation to upvote + a UI change to update the vote count
  • when i go to another page, and then go back to /home, useQuery doesn’t retrieve the products with the correct vote count
  • however, when I check my DB, the products all have the correct vote count.

Why doesuseQuery not return the right amount until i do another page refresh?

for reference, here it is below:

const Home = props => {
  const {data, loading, error} = useQuery(GET_PRODUCTS_LOGGED_IN, {
    variables: {
      userid: props.userid
    }
  });
  
  console.log(
    'data', data.products // this data is outdated after I go from /home -> /profile -> /home
  );

  return (
    <Container>
      {_.map(data.products, product => (
        <VoteButton
          hasVoted={product.hasVoted}
          likes={product.likes}
          productid={product.productid}
        />
      ))}
    </Container>
  );
}
const VoteButton = ({likes, hasVoted, productid}) => {
  const [localHasVoted, updateLocalHasVoted] = useState(hasVoted);
  const [likesCount, updateLikesCount] = useState(likes);
  const [onVote] = useMutation(VOTE_PRODUCT);

  const onClickUpvote = (event) => {
    onVote({
      variables: {
        productid
      }
    })
    updateLocalHasVoted(!localHasVoted);
    updateLikesCount(localHasVoted ? likesCount - 1 : likesCount + 1);
  }
  
  return (
    <VoteContainer onClick={onClickUpvote}>
        <VoteCount >{likesCount}</VoteCount>
    </VoteContainer>
  );
};

Solution

  • On your useQuery call, you can actually pass it a config option called 'fetch-policy' which tells Apollo how you want the query to execute between making the call or using the cache. You can find more information here, Apollo fetch policy options. A quick solution would be be setting fetch-policy to cache and network like the the example below.

      const {data, loading, error} = useQuery(GET_PRODUCTS_LOGGED_IN, {
        variables: {
          userid: props.userid
        },
        fetchPolicy: 'cache-and-network',
      });
    

    You can also make it so that when your mutation happens, it will run your query again by setting the 'refetch-queries' option on useMutation like the code below. This will cause your query to trigger right after the mutation happens. You can read more about it here Apollo mutation options

    const [onVote] = useMutation(VOTE_PRODUCT, {
      refetchQueries: [ {query: GET_PRODUCTS_LOGGED_IN } ],
    });