我正在使用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
答案 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
方法创建一个可观察的对象,该对象会根据缓存的更改进行更新。结果,在最初将组件呈现给服务器端之后,对客户端缓存的任何更改都将触发组件的重新呈现。