変数
上記の例では、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は現在、特定のフラグメントに対して解決された変数(つまり、引数定義を適用した後)を公開していません。また、そうする必要があることはめったにありません。
このページはお役に立ちましたか?
いくつかの簡単な質問に答えることで、サイトの改善にご協力ください。 簡単な質問にお答えください.