Apollo 本地状态 - 使用未知键查询对象
Posted
技术标签:
【中文标题】Apollo 本地状态 - 使用未知键查询对象【英文标题】:Apollo local state - querying for object w unknown keys 【发布时间】:2019-11-01 15:04:06 【问题描述】:我正在尝试将 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 元素的状态,例如:
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
`;
而不是获取 所有 UI 值,然后在组件中找到合适的值。
然而,这会引发错误:
Syntax Error: Invalid number, expected digit but got: "d".
有没有办法执行这样的查询,或者有更好的方法来处理这一切?虽然这种数据结构可能不是惯用的,但似乎 Apollo 应该支持过滤查询,不是吗?
【问题讨论】:
【参考方案1】:我也一直在 apollo 中尝试本地状态管理,所以以下内容有些做作且非常晦涩,但它确实有效。
坦率地说——所有不是标量或数组的东西都需要有一个类型。
所以这个:
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',
,
],
,
)
【讨论】:
以上是关于Apollo 本地状态 - 使用未知键查询对象的主要内容,如果未能解决你的问题,请参考以下文章