Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Apollo useQuery hook doesn't get update from cache with writeQuery() method. No errors seen

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.

like image 690
Paul Sheldon Avatar asked Oct 02 '19 17:10

Paul Sheldon


2 Answers

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

like image 138
Maulik Sakhida Avatar answered Nov 14 '22 06:11

Maulik Sakhida


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 } });
like image 3
ed' Avatar answered Nov 14 '22 05:11

ed'