website/versioned_docs/version-v14.0.0/guided-tour/rendering/variables.md
import DocsRating from '@site/src/core/DocsRating'; import {OssOnly, FbInternalOnly} from 'docusaurus-plugin-internaldocs-fb/internal';
You may have noticed that the query declarations in our examples above contain references to an $id symbol inside the GraphQL code: these are GraphQL Variables.
GraphQL variables are a construct that allows referencing dynamic values inside a GraphQL query. When fetching a query from the server, we also need to provide as input the actual set of values to use for the variables declared inside the query:
query UserQuery($id: ID!) {
# The value of $id is used as input to the user() call:
user(id: $id) {
id
name
}
}
In the above, ID! is the type of the $id variable. That is, it is a required ID.
When sending a network request to fetch the query above, we need to provide both the query, and the variables to be used for this particular execution of the query. For example:
# Query:
query UserQuery($id: ID!) {
# ...
}
# Variables:
{"id": 4}
Fetching the above query and variables from the server would produce the following response, which can also be visualized in GraphiQL:
</FbInternalOnly> <OssOnly>Fetching the above query and variables from the server would produce the following response:
</OssOnly>{
"data": {
"user": {
"id": "4",
"name": "Mark Zuckerberg"
}
}
}
Fragments can also reference variables that have been declared by a query:
fragment UserFragment on User {
name
profile_picture(scale: $scale) {
uri
}
}
query ViewerQuery($scale: Float!) {
viewer {
actor {
...UserFragment
}
}
}
$scale variable directly, it can still reference it. Doing so makes it so any query that includes this fragment, either directly or transitively, must declare the variable and its type, otherwise an error will be produced.In Relay, fragment declarations inside components can also reference query variables:
function UserComponent(props: Props) {
const data = useFragment(
graphql`
fragment UserComponent_user on User {
name
profile_picture(scale: $scale) {
uri
}
}
`,
props.user,
);
return (...);
}
$scale variable.$scale variable, an error will be produced by the Relay Compiler at build time, ensuring that an incorrect query never gets sent to the server (sending a query with missing variable declarations will also produce an error in the server).However, in order to avoid bloating queries with global variable declarations and to allow developers to reuse fragments with different variables, Relay also provides a way to declare variables that are scoped locally to a fragment using the @arguments and @argumentDefinitions directives:
/**
* Declare a fragment that accepts arguments with @argumentDefinitions
*/
function PictureComponent(props) {
const data = useFragment(
graphql`
fragment PictureComponent_user on User
@argumentDefinitions(scale: {type: "Float!"}) {
profile_picture(scale: $scale) {
uri
}
}
`,
props.user,
);
}
/**
* Include fragment using @arguments
*/
function UserComponent(props) {
const data = useFragment(
graphql`
fragment UserComponent_user on User {
name
# Pass value of 2.0 for the $scale variable
...PictureComponent_user @arguments(scale: 2.0)
}
`,
props.user,
);
}
/**
* Include same fragment using *_different_* @arguments
*/
function OtherUserComponent(props) {
const data = useFragment(
graphql`
fragment OtherUserComponent_user on User {
name
# Pass a different value for the scale variable.
# The value can be a local variable, global variable or literal:
...PictureComponent_user @arguments(scale: $pictureScale)
}
`,
props.user,
);
}
@arguments to a fragment, we can pass a literal value or pass another variable. The variable can be a global query variable, a local variable declared via @argumentDefinitions or a literal (e.g. 42.0).PictureComponent_user as part of a query, the scale value passed to the profile_picture field will depend on the argument that was provided by the parent of PictureComponent_user:
UserComponent_user the value of $scale will be 2.0.OtherUserComponent_user, the value of $scale will be whatever value we pass to the server for the $pictureScale variable when we fetch the query.Fragments that expect arguments can also declare default values, making the arguments optional:
/**
* Declare a fragment that accepts arguments with default values
*/
function PictureComponent(props) {
const data = useFragment(
graphql`
fragment PictureComponent_user on User
@argumentDefinitions(scale: {type: "Float!", defaultValue: 2.0}) {
# $scale is a local variable here, declared above
# as an argument scale, of type Float! with a default value of 2.0
profile_picture(scale: $scale) {
uri
}
}
`,
props.user,
);
}
function UserComponent(props) {
const data = useFragment(
graphql`
fragment UserComponent_user on User {
name
# Do not pass an argument, value for scale will be 2.0
...PictureComponent_user
}
`,
props.user,
);
}
PictureComponent_user makes it use the default value for its locally declared $scale variable, in this case 2.0.If you want to access the variables that were set at the query root, the recommended approach is to pass the variables down the component tree in your application, using props, or your own application-specific context.
Relay currently does not expose the resolved variables (i.e. after applying argument definitions) for a specific fragment, and you should very rarely need to do so.
<DocsRating />