变量
您可能已经注意到,我们上面示例中的查询声明包含对 GraphQL 代码中的 $id
符号的引用:这些是 GraphQL 变量。
GraphQL 变量是一种构造,允许在 GraphQL 查询中引用动态值。从服务器获取查询时,我们还需要提供作为输入的实际值集,用于查询中声明的变量。
query UserQuery($id: ID!) {
# The value of $id is used as input to the user() call:
user(id: $id) {
id
name
}
}
在上面,ID!
是 $id
变量的类型。也就是说,它是一个必需的 ID。
当发送网络请求来获取上面的查询时,我们需要提供查询和用于此特定查询执行的变量。例如
# Query:
query UserQuery($id: ID!) {
# ...
}
# Variables:
{"id": 4}
从服务器获取上面的查询和变量将产生以下响应
{
"data": {
"user": {
"id": "4",
"name": "Mark Zuckerberg"
}
}
}
片段也可以引用由查询声明的变量
fragment UserFragment on User {
name
profile_picture(scale: $scale) {
uri
}
}
query ViewerQuery($scale: Float!) {
viewer {
actor {
...UserFragment
}
}
}
- 即使上面的片段没有直接声明
$scale
变量,它仍然可以引用它。这样做使得任何包含此片段的查询(直接或间接)必须声明该变量及其类型,否则将产生错误。 - 换句话说,查询变量对任何作为查询后代的片段全局可用。
- 引用全局变量的片段只能包含(直接或间接)在定义该全局变量的查询中。
在 Relay 中,组件中的片段声明也可以引用查询变量
function UserComponent(props: Props) {
const data = useFragment(
graphql`
fragment UserComponent_user on User {
name
profile_picture(scale: $scale) {
uri
}
}
`,
props.user,
);
return (...);
}
- 上面的片段可以被多个查询包含,并由不同的组件呈现,这意味着任何最终呈现/包含上面片段的查询必须声明
$scale
变量。 - 如果任何包含此片段的查询没有声明
$scale
变量,Relay 编译器将在构建时产生错误,确保错误的查询永远不会发送到服务器(发送缺少变量声明的查询也会在服务器中产生错误)。
@arguments 和 @argumentDefinitions
Relay 还提供了一种方法,可以使用@arguments
和@argumentDefinitions
指令声明局部作用于片段的变量。使用局部变量的片段易于定制和重用,因为它们不依赖于全局(查询级)变量的值。
/**
* Declare a fragment that accepts arguments with @argumentDefinitions
*/
function TaskView(props) {
const data = useFragment(
graphql`
fragment TaskView_task on Task
@argumentDefinitions(showDetailedResults: {type: "Boolean!"}) {
name
is_completed
... @include(if: $showDetailedResults) {
description
}
}
`,
props.task,
);
}
/**
* Include fragment using @arguments
*/
function TaskList(props) {
const data = usePreloadedQuery(
graphql`
query TaskListQuery {
todays_tasks {
...TaskView_task @arguments(showDetailedResults: true)
}
tomorrows_tasks {
...TaskView_task @arguments(showDetailedResults: false)
}
}
`,
props.queryRef,
);
}
局部作用域的变量也有助于从其他查询中重用片段。
查询定义必须列出所有由任何嵌套片段使用的变量,包括递归嵌套的片段。
由于片段可能从多个查询访问,因此修改使用全局变量的片段可能需要更改许多查询定义。
这也可能导致尴尬的情况,比如具有多个版本的“相同”变量,例如
$showDetailedResults
和$showDetails
。由于只有局部作用域变量的片段不使用全局变量,因此它们不会遇到此问题。
请注意,当将
@arguments
传递给片段时,我们可以传递字面量值或传递另一个变量。该变量可以是全局查询变量、通过@argumentDefinitions
声明的局部变量或字面量(例如42.0
)。当我们实际获取
TaskView_task
作为查询的一部分时,showDetailedResults
的值将取决于TaskView_task
的父级提供的参数。
期望参数的片段也可以声明默认值,使参数可选
/**
* Declare a fragment that accepts arguments with default values
*/
function TaskView(props) {
const data = useFragment(
graphql`
fragment TaskView_task on Task
@argumentDefinitions(showDetailedResults: {type: "Boolean!", defaultValue: true}) {
name
is_completed
... @include(if: $showDetailedResults) {
description
}
}
`,
props.task,
);
}
function TaskList(props) {
const data = usePreloadedQuery(
graphql`
query TaskListQuery {
todays_tasks {
...TaskView_task
}
tomorrows_tasks {
...TaskView_task @arguments(showDetailedResults: false)
}
}
`,
props.queryRef,
);
}
- 不将参数传递给
TaskView_task
使其使用其局部声明的$showDetailedResult
变量的默认值。
在运行时访问 GraphQL 变量
如果您想访问在查询根目录设置的变量,建议的方法是使用 props 或您自己的应用程序特定上下文将变量传递到应用程序的组件树中。
Relay 目前不公开特定片段的解析变量(即在应用参数定义后的变量),并且您很少需要这样做。
此页面是否有用?
通过以下方式帮助我们改进网站: 回答一些简短的问题.