javascript - 下一个/React-Apollo : React props not hooked up to apollo cache when query comes from getInitialProps

标签 javascript reactjs apollo next.js react-apollo

我正在使用nextjs和react-apollo(带钩子(Hook))。我正在尝试在突变后更新 Apollo 缓存中的用户对象(我不想重新获取)。发生的情况是,用户似乎在缓存中得到了很好的更新,但组件使用的用户对象没有得到更新。相关代码如下:

页面:

// pages/index.js

...

const Page = ({ user }) => {
  return <MyPage user={user} />;
};


Page.getInitialProps = async (context) => {
  const { apolloClient } = context;
  const user = await apolloClient.query({ query: GetUser }).then(({ data: { user } }) => user);

  return { user };
};

export default Page;

以及组件:

// components/MyPage.jsx

...

export default ({ user }) => {
  const [toggleActive] = useMutation(ToggleActive, {
    variables: { id: user.id },
    update: proxy => {
      const currentData = proxy.readQuery({ query: GetUser });

      if (!currentData || !currentData.user) {
        return;
      }

      console.log('user active in update:', currentData.user.isActive);

      proxy.writeQuery({
        query: GetUser,
        data: {
          ...currentData,
          user: {
            ...currentData.user,
            isActive: !currentData.user.isActive
          }
        }
      });
    }
  });

  console.log('user active status:', user.isActive);

  return <button onClick={toggleActive}>Toggle active</button>;
};

当我连续按下按钮时,更新功能中的控制台日志显示用户事件状态来回翻转,因此看来apollo缓存正在正确更新。但是,组件中的控制台日志始终显示相同的状态值。

我没有看到我正在执行的任何其他 apollo 缓存更新发生此问题,其中组件使用的数据对象是使用 useQuery Hook 在组件中获取的(即不是从 getInitialProps 中的查询获取的)。

请注意,我的 apollo ssr 设置与官方 nextjs 示例非常相似:https://github.com/zeit/next.js/tree/canary/examples/with-apollo

最佳答案

问题在于您正在调用客户端的query 方法。此方法只是向服务器发出请求并返回解析为响应的 Promise。因此,在渲染页面之前调用 getInitialProps,调用 query,Promise 解析,然后将生成的用户对象作为 prop 传递给页面组件。对缓存的更新不会触发再次运行 getInitialProps (尽管我相信导航离开和导航回来应该),因此 user prop 在初始渲染后永远不会改变。

如果您想订阅缓存中的更改,则应使用 useQuery Hook ,而不是使用 query 方法和 getInitialProps 。您还可以使用 Query 组件或 graphql HOC 达到相同的效果,尽管这两个组件现在已被弃用,取而代之的是新的 hooks API。

export default () => {
  const { data: { user } = {} } = useQuery(GetUser)
  const [toggleActive] = useMutation(ToggleActive, { ... })

  ...
})

样板代码中使用的 getDataFromTree 方法(与设置初始缓存状态相结合)可确保运行使用 useQuery Hook 为页面获取的任何查询在页面渲染之前,添加到缓存并用于实际的服务器端渲染。

useQuery 利用客户端的 watchQuery 方法创建一个可观察对象,该可观察对象会根据缓存的更改进行更新。因此,在组件最初在服务器端渲染后,客户端缓存的任何更改都将触发组件的重新渲染。

关于javascript - 下一个/React-Apollo : React props not hooked up to apollo cache when query comes from getInitialProps,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59331462/

相关文章:

javascript - 为什么代码停止检查是否是数组?

javascript - 如何在 angular.js 中将 div 的所有内容从西类牙语翻译成英语?

javascript - 对象文字比较的奇怪行为

javascript - 使用react,可以制作一个使用axios、setInterval、setTimeout和map的应用程序吗?

reactjs - 为什么我们需要 Gatsby 项目文件结构中的模板文件夹

android - 如何手动将 Apollo Android 生成的对象转换为 JSON 字符串并返回?

javascript - 如果 div 有图像,则将该 img 放在其他 div 中

javascript - React 嵌套渲染

graphql - 如何解决 "Payload is not serializable: Converting circular structure to JSON"错误?

reactjs - NextJS/Typescript/Apollo 错误;属性在类型上不存在