嗨,当我尝试将@apollo/client: latest
与next:latest
,useQuery
挂钩和阿波罗缓存一起使用时,会遇到一些问题。
所以一步一步来:
我在_app.js
文件中使用了with-apollo HOC(来自Next示例)。
创建Apollo客户端时,我会初始化状态并将其传递给ApolloCache
export default function createApolloClient(initialState, ctx) {
const cache = new InMemoryCache();
cache.writeData({
data: {
config: {
first: 10,
__typename: 'CONFIG',
},
},
});
// The `ctx` (NextPageContext) will only be present on the server.
// use it to extract auth headers (ctx.req) or similar.
return new ApolloClient({
ssrMode: Boolean(ctx),
link: new HttpLink({
uri: 'https://api.graph.cool/simple/v1/cixmkt2ul01q00122mksg82pn', // Server URL (must be absolute)
credentials: 'same-origin', // Additional fetch() options like `credentials` or `headers`
fetch,
}),
cache,
typeDefs,
resolvers: {},
});
}
在原始项目状态下基于请求标头生成的,这里我使用一些复制示例;
在_app.js
中,组件由ConfigProvider封装,它以这种方式从阿波罗缓存中查询数据:
export const CONFIG_QUERY = gql`
query config {
config @client {
first
}
}
`;
export const ConfigProvider = ({ children }) => {
const { data, loading } = useQuery(CONFIG_QUERY);
console.log('loading', loading);
const config = data ? data.config : {};
return (
<ConfigContext.Provider value={config}>{children}</ConfigContext.Provider>
);
};
在ConfigProvider ConfigConusmer将config
传递给PostsProvider之后,PostsProvider在另一个useQuery中使用该配置
export const PostsProvider = ({ children, config }) => {
const { data } = useQuery(ALL_POSTS_QUERY, {
variables: { ...allPostsQueryVars, first: config.first }
});
const allPosts = data ? data.allPosts : [];
return (
<PostsContext.Provider value={allPosts}>{children}</PostsContext.Provider>
);
};
问题是,即使ConfigProvider中的缓存getDataFromTree()
中已经有配置,但下次执行useQuery
时,总是总是先返回loading: true
和data: undefined
,这使PostProvider的变量损坏了并且getDataFromTree引发错误。结果是所有PostProvider查询都在客户端而不是服务器端被调用。
有人可以为我解释这种行为吗?即使数据已经在阿波罗缓存中,为什么第一次遍历仍返回未定义状态?有办法使它起作用吗?
这是一个Codesanbox示例https://codesandbox.io/s/trusting-sinoussi-qw4qi