9

After using useMutation(), cache gets updated but useQuery() in Home component doesn't.

I tried with a different fetchPolicy. I can see new posts in Apollo dev tool but the page needs to be updated to see the changes

import { FETCH_POSTS_QUERY } from '../utils/graphql';

function Home() {
  const { user } = useContext(AuthContext);
  const {
    loading,
    data
  } = useQuery(FETCH_POSTS_QUERY, {
    fetchPolicy: 'cache-and-network',
  });
...

import { useMutation } from '@apollo/react-hooks';

import { useForm } from '../utils/hooks';
import { FETCH_POSTS_QUERY } from '../utils/graphql';

function PostForm() {
  const { values, onChange, onSubmit } = useForm(createPostCallback, {
    body: ''
  });

  const [createPost, { error }] = useMutation(CREATE_POST_MUTATION, {
    variables: values,
    update(proxy, result) {
      const data = proxy.readQuery({
        query: FETCH_POSTS_QUERY
      });
      data.getPosts.push(result.data.createPost);
      proxy.writeQuery({ query: FETCH_POSTS_QUERY, data });
      values.body = '';
    }
  });

  function createPostCallback() {
    createPost();
  }
...
...
import { InMemoryCache } from 'apollo-cache-inmemory';
import { createHttpLink } from 'apollo-link-http';
import { ApolloProvider } from '@apollo/react-hooks';
import { setContext } from 'apollo-link-context';

const httpLink = createHttpLink({
  uri: 'http://localhost:5000'
});

const authLink = setContext(() => {
  const token = localStorage.getItem('jwttoken');
  return {
    headers: {
      Authorization: token ? `Bearer ${token}` : ''
    }
  };
});

const client = new ApolloClient({
  link: authLink.concat(httpLink),
  cache: new InMemoryCache()
});

...

I expect seeing the new post without updating the page.

Vikram Deshmukh
  • 12,304
  • 4
  • 36
  • 38
Paul Sheldon
  • 93
  • 1
  • 4

3 Answers3

6

This code snippet solve the problem with frontend refresh when you write the cache with PostForm:

//in Home.js use this:

const [posts, setPosts] = useState([]);
const { user } = useContext(AuthContext);
const { loading, data } = useQuery(FETCH_POSTS_QUERY);
useEffect(() => {
    if (data) {
        setPosts(data.getPosts);
    }
}, [data]);

and in PostForm.js use this:

const [createPost, { error }] = useMutation(CREATE_POST_MUTATION, {
    variables: values,
    update(proxy, result) {
        const data = proxy.readQuery({
            query: FETCH_POSTS_QUERY
        });
        const new_post = result.data.createPost;
        proxy.writeQuery({
            query: FETCH_POSTS_QUERY,
            data: { getPosts: [new_post, ...data.getPosts] }
        });
        values.body = '';
    }
});

This solution was not my idea, but one code hero help us :)

Reference Link :https://gist.github.com/josuecatalan/5b8bf73e69d55683ccf237d5d02b5cef

Original Content: https://www.youtube.com/watch?v=F_SdB42DxdQ&list=PLMhAeHCz8S3_pgb-j51QnCEhXNj5oyl8n&index=6

Maulik Sakhida
  • 471
  • 4
  • 15
3

You are modifying the cached data with push here:

data.getPosts.push(result.data.createPost);

and then returning it as is

proxy.writeQuery({ query: FETCH_POSTS_QUERY, data });

as this is javascript and objects are passed by reference the data you returned is the same object you received, so apollo doesn't realise it has changed. Try the following:

proxy.writeQuery({ query: FETCH_POSTS_QUERY, data: { ...data } });
ed'
  • 1,815
  • 16
  • 30
  • now it's not updating cache if I do like this ```javascript data.getPosts = [result.data.createPost, ...data.getPosts] ``` it's working as previous – Paul Sheldon Oct 03 '19 at 07:48
  • you are still modifying the same `data` object, try to do it as I have written and create new `data` – ed' Oct 03 '19 at 08:59
  • I am having the same issue. Any solution? – kenrickvaz Dec 27 '19 at 06:18
  • The solution is as written in my post. If you aren't able to fix it, you either don't have the same problem as the OP or you are still re-using the cache object. Update cache with a new object, every time. – ed' Dec 27 '19 at 12:40
0

In my case backend team just rewrote uploaded image file and leaved the old name. So an application UI didn't want to rerender. And I wasted few hours to debug it. So don't forget to check the data as well.

Aliaksei
  • 1,094
  • 11
  • 20