API: graphql 容器
graphql(query, [config])(component)
|
|
graphql()
函数是 react-apollo
中最重要的部分。使用此函数,你可以创建基于 Apollo store 中的数据来反应性地执行查询和更新的高阶组件。graphql()
函数返回一个函数,它将“增强”任何具有反应性 GraphQL 功能的组件。这与 react-redux
的 connect
函数使用的 React 高阶组件模式一致。
graphql()
函数可以这样使用:
|
|
你还可以定义一个中间函数,使用 graphql()
函数将组件联接起来,如下所示:
|
|
或者,你还可以在 React 类组件上使用 graphql()
函数作为装饰器。
如果是这样,你的代码可能如下所示:
|
|
如果你的组件树根部有一个 <ApolloProvider/>
组件提供一个 ApolloClient
实例用于获取数据,graphql()
函数将只能提供对 GraphQL 数据的访问。
根据 GraphQL 的操作是一个查询,还是一个突变,或是一个订阅,你使用 graphql()
函数增强的组件的行为会有所不同。有关每种类型的功能和可用选项的更多信息,请参阅相应的API文档。
在我们研究每种操作的具体行为之前,让我们先看看 config
对象。
config
在你的 GraphQL 文本之后,config
对象是你传入 graphql()
函数的第二个参数。该配置是可选的,并允许你向高阶组件添加一些自定义行为。
|
|
让我们来看看你的 config
对象所有可能的属性。
config.options
config.options
是一个对象或函数,它允许你定义组件在处理 GraphQL 数据时应使用的具体行为。
可用于配置的具体选项取决于你为 graphql()
传递的第一个参数 – 操作类型。针对查询和突变,有特定的选项可以配置。
你可以将 config.options
定义为普通对象,或者你可以从一个函数中计算你的选项,该函数接收组件的 props 作为参数。
例:
|
|
|
|
config.props
config.props
属性允许你定义一个 map 函数,它包含你的所有 props,包括由 graphql()
函数(用于查询的 props.data
,用于突变的 props.mutate
)添加的属性,并且允许你计算一个新的 props 对象,提供给graphql()
正在包装的组件。
你定义的函数几乎与 Recompose 中的 mapProps
完全一样,提供了相同的便利,并且不需要引入一个新的库。
如果你想将复杂的函数调用抽象成一个简单的,可以传递给你的组件的 prop,那么 config.props
是最有用的。
config.props
的另一个好处,是它也允许你将你的纯 UI 组件与 GraphQL 和 Apollo 的关系分离开来。你可以将纯 UI 组件写在一个文件里,然后保留所需的逻辑,以便它们在项目中别的地方与 store 进行交互。你可以通过只需要渲染所需的 props 的纯 UI 组件实现这个,config.props
可以包含从 GraphQL API 提供的数据中完全提供你的纯组件所需的 props 的逻辑。
例:
此示例使用了 props.data.fetchMore
。
|
|
config.skip
如果 config.skip
值为真,那么所有的 React Apollo 代码将被完全跳过。就好像graphql()
函数是一个简单的标识函数。你的组件将会像 graphql()
函数不存在那般。
除了将布尔值传递给 config.skip
,你也可以将函数传递给 config.skip
。该函数将接收你的组件 props,并返回一个布尔值。如果布尔值返回真,则跳过行为将生效。
如果你想要基于某些 prop 使用不同的查询,config.skip
将会十分有用。你可以在下面的示例中看到这一点。
例:
|
|
以下示例使用 compose()
函数同时使用多个 graphql()
增强器。
|
|
config.name
该属性允许你配置传递给组件的 prop 的名称。默认情况下,如果你传递给 graphql()
的 GraphQL 文本是一个查询,那么你的 prop 将被命名为 data
。如果你传递的是一个突变,那么你的 prop 将被命名为 mutate
。当你尝试为同一个组件的使用多个查询或突变时,这些默认名称会相互冲突。为了避免冲突,你可以使用 config.name
为每个查询或突变高阶组件提供一个新的名字给 prop。
例:
此示例使用 compose
函数将多个 graphql()
高阶组件组合在一起。
|
|
config.withRef
通过将 config.withRef
设置为真,你可以使用高阶 GraphQL 组件实例上的 getWrappedInstance
方法从该高阶 GraphQL 组件实例获取包裹组件。
当你想要调用在包裹组件的类实例上定义的函数或访问其属性时,可能需要将其设置为真。
下面是一个这种情况下的例子。
例:
此示例使用 React ref
功能。
|
|
config.alias
默认情况下,React Apollo 组件的显示名称为 Apollo(${WrappedComponent.displayName})
。这是大多数使用高阶组件的 React 库所使用的模式。但是,当你使用多个高阶组件时查看 [React Devtools][],可能会有点困惑。
如果要配置高阶组件包装器的名称,可以使用 config.alias
属性。因此,假设你将 config.alias
设置为 'withCurrentUser'
,你的包装器组件显示名称将是 withCurrentUser(${WrappedComponent.displayName})
,而不是 Apollo(${WrappedComponent.displayName})
。
例:
此示例使用 compose
函数将多个 graphql()
高阶组件组合在一起。
|
|
compose(...enhancers)(component)
|
|
为了实用目的,react-apollo
导出一个 compose
函数。使用此函数,你可以利落地一次使用多个组件增强器。包括多个 graphql()
,withApollo()
或 Redux connect()
增强器。当你使用多个增强器时,这将会理清你的代码。 Redux 也导出一个 compose
函数,Recompose 也是如此,所以你可以有选择地从合适的库中使用这个函数。
一个重要的注意事项是,compose()
首先执行最后一个增强器,并根据增强器列表依次向后执行。为了说明这种情况,我们调用三个函数:funcC(funcB(funcA(component)))
相当于这样调用 compose()
:compose(funcC, funcB, funcA)(component)
。如果还不明白,你可以想象 [Lodash 中的flowRight()
][] 函数,它们具有相同的行为。
例:
|
|