我正在尝试将Apollo添加到应用中。我将使用它来获取数据,并希望遵循最佳实践并使用新的API(从Apollo 2.5开始)来存储本地UI状态。
我一直在研究these docs,但是它们的UI状态比我要实现的状态更简单。
我想移植我在Redux应用程序中一直使用的模式,其中许多UI元素的值都集中存储在其中。在Redux中,我有一个reducer对象,用于存储UI值,如下所示:
{
dropdowns: {
someDropdown: [{ index: 0, value: 'Selected Value' }]
},
checkboxes: {
someCheckbox: true
}
}
如图所示,不同类型的元素表示为对象,对于每个对象,每个键都是UI元素的唯一ID,并且值根据元素类型而变化。
我也喜欢上面的拼合版本,其中没有按UI元素类型的子分类。
我还有一个单独的reducer,用于存储某些UI元素的 state ,例如:
{
openDropdownId: 'someDropdown',
openModalId: null
}
至关重要的是,该数据似乎包含其键不可预测的对象。我既不确定如何使用
gql
进行键入,也不确定如何有效地获取此数据(请参阅问题底部)。
我曾尝试使用Apollo Client来重现此内容,但遇到了大量错误。这是我的客户端设置:
例如,对于一个下拉列表,想法是
states
在此处存储打开/关闭状态,而values
存储有关所选值的信息。
import { ApolloClient } from 'apollo-client';
import { InMemoryCache } from 'apollo-cache-inmemory';
import gql from 'graphql-tag';
const typeDefs = gql`
extend type UI {
states: Object
values: Object
}
`;
const defaults = {
ui: {
__typename: 'UI',
states: {},
values: {}
}
};
const cache = new InMemoryCache();
const client = new ApolloClient({
cache,
resolvers: {},
typeDefs
});
console.log({ defaults });
cache.writeData({ data: defaults });
export default client;
然后我像这样使用该客户端:
<ApolloProvider client={client}>
<App />
</ApolloProvider>
这是引发错误的查询示例:
const QUERY = gql`
{
ui @client {
states
values
}
}
`;
我看到的错误是:
Uncaught Invariant Violation: Missing selection set for object of type undefined returned for query field states
该错误显示在查询组件中。
我还收到两个警告(可能是states
的警告和values
的警告)
Missing field __typename in {}
我是否需要以不同的方式构造数据以查询这样的数据?
后续问题:如果组件具有UID,最好能够查询其值,例如:
const QUERY = gql`
{
ui @client {
states {
${uid}
}
values {
${uid}
}
}
}
`;
代替获取 all UI值,然后在组件中找到合适的UI值。
但是会引发错误:
Syntax Error: Invalid number, expected digit but got: "d".
是否有一种方法可以执行这样的查询,或者有更好的方法来处理所有这些问题?尽管此数据结构可能不是惯用的,但似乎Apollo应该为过滤查询支持此数据,不是吗?
答案 0 :(得分:2)
我也曾在阿波罗进行地方状态管理的实验,因此以下内容有些人为设计且非常晦涩,但确实可行。
直言不讳地将所有非标量或数组上的东西都必须具有类型。
所以这个:
const defaults = {
ui: {
__typename: 'UI',
states: {},
values: {}
}
};
需要成为例如:
const defaults = {
ui: {
__typename: 'UI',
states: {
__typename: 'UIStates'
},
values: {
__typename: 'UIValues'
}
}
};
并且在您的查询中必须引用标量或数组,因此自然地您的查询将不起作用:
const QUERY = gql`
{
ui @client {
states
values
}
}
`;
您需要更深入地研究标量或数组:
const QUERY = gql`
{
ui @client {
states {
foo
}
values {
bar
}
}
}
`;
其余的取决于您的数据。
如果您需要过滤查询-您的查询将如下所示(第一个查询返回所有项目,下一个查询通过ID过滤项目)
const TEST_CLIENT_FILTER_QUERY = gql`
{
bzz @client {
id
title
}
bzz(id: $id) @client {
id
title
}
}
`
您也将需要一个解析器。这是很脏的,我不确定这是 apollo-graphql 的方式,但是目前为止它对我来说还是有用的。
resolvers: {
Query: {
bzz: (root, variables, context) => {
const key = context.getCacheKey({ __typename: 'bzz', id: variables.id })
return context.cache.extract()[key]
},
},
},
这些是我对此类查询的默认设置:
cache.writeData({
data: {
bzz: [
{
__typename: 'bzz',
id: 1,
title: 'bzz 1',
},
{
__typename: 'bzz',
id: 2,
title: 'bzz 2',
},
],
},
})