Next / React-Apollo:当查询来自getInitialProps时,React道具未连接到Apollo缓存

时间:2019-12-14 00:56:39

标签: javascript reactjs apollo next.js react-apollo

我正在使用nextjs和react-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>;
};

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

我看不到我正在执行的任何其他阿波罗缓存更新发生的问题,其中使用useQuery挂钩(即,不是从getInitialProps中的查询)在组件中获取组件使用的数据对象。 / p>

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

1 个答案:

答案 0 :(得分:1)

问题在于您正在调用客户端的query方法。此方法只是向服务器发出请求,并返回一个解析为响应的Promise。因此,getInitialProps在呈现页面之前被调用,query被调用,Promise解析,并且您将作为结果的用户对象向下传递给页面组件。缓存的更新不会触发getInitialProps再次运行(尽管我认为应该离开并向后导航),因此用户属性在初始渲染后将永远不会改变。

如果要预订缓存中的更改,则应使用query钩子,而不要使用getInitialProps方法和useQuery。您也可以使用Query组件或graphql HOC来达到相同的效果,尽管现在两者都已弃用,而使用了新的hooks API。

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

  ...
})

样板代码中使用的getDataFromTree方法(与设置初始缓存状态结合使用)确保使用useQuery钩子为您的页面提取的所有查询均在之前运行页面渲染,将其添加到缓存中并用于实际的服务器端渲染。

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