Next/React-Apollo:当查询来自 getInitialProps 时,React props 没有连接到 apollo 缓存
Next/React-Apollo: React props not hooked up to apollo cache when query comes from getInitialProps
我正在使用 nextjs 和 react-apollo(带钩子)。我正在尝试在突变后更新 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 缓存更新中,其中组件使用的数据对象是使用 useQuery 挂钩在组件中获取的(即不是来自 getInitialProps 中的查询) .
请注意,我的 apollo ssr 设置与官方 nextjs 示例非常相似:https://github.com/zeit/next.js/tree/canary/examples/with-apollo
问题是您正在调用客户端的 query
方法。此方法只是向服务器发出请求,并 returns 解析为响应的 Promise。因此 getInitialProps
在页面呈现之前被调用, query
被调用,Promise 解析并且您将生成的用户对象作为道具传递给您的页面组件。对缓存的更新不会触发 getInitialProps
再次成为 运行(尽管我相信导航离开和导航回来应该),因此用户属性在初始渲染后永远不会改变。
如果您想订阅缓存中的更改,而不是使用 query
方法和 getInitialProps
,您应该使用 useQuery
挂钩。您也可以使用 Query
组件或 graphql
HOC 来达到相同的效果,尽管这两个现在都已弃用,取而代之的是新的挂钩 API.
export default () => {
const { data: { user } = {} } = useQuery(GetUser)
const [toggleActive] = useMutation(ToggleActive, { ... })
...
})
样板代码中使用的 getDataFromTree
方法(结合设置初始缓存状态)确保使用 useQuery
挂钩为您的页面提取的任何查询都是 运行 在页面呈现之前,添加到您的缓存中并用于实际的服务器端呈现。
useQuery
利用客户端的 watchQuery
方法创建一个 observable,它根据缓存的变化进行更新。因此,在组件最初在服务器端呈现后,对客户端缓存的任何更改都将触发组件的重新呈现。
我正在使用 nextjs 和 react-apollo(带钩子)。我正在尝试在突变后更新 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 缓存更新中,其中组件使用的数据对象是使用 useQuery 挂钩在组件中获取的(即不是来自 getInitialProps 中的查询) .
请注意,我的 apollo ssr 设置与官方 nextjs 示例非常相似:https://github.com/zeit/next.js/tree/canary/examples/with-apollo
问题是您正在调用客户端的 query
方法。此方法只是向服务器发出请求,并 returns 解析为响应的 Promise。因此 getInitialProps
在页面呈现之前被调用, query
被调用,Promise 解析并且您将生成的用户对象作为道具传递给您的页面组件。对缓存的更新不会触发 getInitialProps
再次成为 运行(尽管我相信导航离开和导航回来应该),因此用户属性在初始渲染后永远不会改变。
如果您想订阅缓存中的更改,而不是使用 query
方法和 getInitialProps
,您应该使用 useQuery
挂钩。您也可以使用 Query
组件或 graphql
HOC 来达到相同的效果,尽管这两个现在都已弃用,取而代之的是新的挂钩 API.
export default () => {
const { data: { user } = {} } = useQuery(GetUser)
const [toggleActive] = useMutation(ToggleActive, { ... })
...
})
样板代码中使用的 getDataFromTree
方法(结合设置初始缓存状态)确保使用 useQuery
挂钩为您的页面提取的任何查询都是 运行 在页面呈现之前,添加到您的缓存中并用于实际的服务器端呈现。
useQuery
利用客户端的 watchQuery
方法创建一个 observable,它根据缓存的变化进行更新。因此,在组件最初在服务器端呈现后,对客户端缓存的任何更改都将触发组件的重新呈现。