Apollo useQuery 钩子不会使用 writeQuery() 方法从缓存中获取更新。没有看到错误

Posted

技术标签:

【中文标题】Apollo useQuery 钩子不会使用 writeQuery() 方法从缓存中获取更新。没有看到错误【英文标题】:Apollo useQuery hook doesn't get update from cache with writeQuery() method. No errors seen 【发布时间】:2020-02-01 00:12:57 【问题描述】:

使用useMutation() 后,缓存会更新,但主页组件中的useQuery() 不会。

我尝试使用不同的fetchPolicy。我可以在 Apollo 开发工具中看到新帖子,但需要更新页面才能看到更改

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()
);

...

我希望在不更新页面的情况下看到新帖子。

【问题讨论】:

【参考方案1】:

这段代码sn-p解决了你用PostForm写缓存时前端刷新的问题:

//在 Home.js 中使用这个:

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

在 PostForm.js 中使用这个:

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 = '';
    
);

这个解决方案不是我的主意,但一位代码英雄帮助我们:)

参考链接:https://gist.github.com/josuecatalan/5b8bf73e69d55683ccf237d5d02b5cef

原创内容: https://www.youtube.com/watch?v=F_SdB42DxdQ&list=PLMhAeHCz8S3_pgb-j51QnCEhXNj5oyl8n&index=6

【讨论】:

【参考方案2】:

您在此处使用push 修改缓存数据:

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

然后原样返回

proxy.writeQuery( query: FETCH_POSTS_QUERY, data );

因为这是 javascript 并且对象是通过引用传递的,所以您返回的 data 与您收到的对象相同,所以 apollo 没有意识到它已经改变了。请尝试以下操作:

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

【讨论】:

现在它不会更新缓存,如果我喜欢这个javascript data.getPosts = [result.data.createPost, ...data.getPosts] 它就像以前一样工作 你还在修改同一个data对象,试着按照我写的那样做并创建新的data 我遇到了同样的问题。有什么解决办法吗? 解决方案如我的帖子中所写。如果您无法修复它,那么您要么没有与 OP 相同的问题,要么您仍在重新使用缓存对象。每次都使用新对象更新缓存。【参考方案3】:

就我而言,后端团队只是重写了上传的图像文件并保留了旧名称。所以应用程序 UI 不想重新渲染。我浪费了几个小时来调试它。 所以不要忘记检查数据。

【讨论】:

以上是关于Apollo useQuery 钩子不会使用 writeQuery() 方法从缓存中获取更新。没有看到错误的主要内容,如果未能解决你的问题,请参考以下文章

Apollo 客户端没有读取使用 useQuery 钩子传入的变量

如何在 react/apollo 中调用条件 useQuery 钩子

@apollo/client 反应钩子 useQuery() 数据未定义

在@apollo/react-hooks 的 useQuery 钩子中忽略了跳过参数

如何使用 Apollo 客户端 useQuery 钩子防止不必要的重新获取?

如何将 React 钩子(useContext、useEffect)与 Apollo 反应钩子(useQuery)结合起来