Launch GraphOS Studio

Using GraphQL directives in Apollo Client

Configure GraphQL fields and fragments

A decorates part of a or with additional configuration. Tools like can read a GraphQL 's directives and perform custom logic as appropriate.

are preceded by the @ character, like so:

query myQuery($someTest: Boolean) {
experimentalField @skip(if: $someTest)

This example shows the @skip , which is a built-in directive (i.e., it's part of the GraphQL specification). It demonstrates the following about :

  • can take of their own (if in this case).
  • appear after the declaration of what they decorate (the experimentalField in this case).


The @client allows you to resolve client-only data alongside your server data. These are not sent to the .

query LaunchDetails($launchId: ID!) {
launch(id: $launchId) {
rocket {
# resolved locally on the client,
# removed from the request to the server
description @client

For more information about the @client , see this section on local-only fields. The @client is also useful for client schema mocking before a given is supported in the API your application is consuming.


The @connection allows you to specify a custom cache key for paginated results. For more information, see this section on the @connection directive.

query Feed($offset: Int, $limit: Int) {
feed(offset: $offset, limit: $limit) @connection(key: "feed") {


Beginning with version 3.7.0, provides preview support for the @defer directive. This enables your queries to receive data for specific incrementally, instead of receiving all data at the same time. This is helpful whenever some fields in a take much longer to resolve than others.

To use the @defer , we apply it to an inline or named that contains all slow-resolving :

query PersonQuery($personId: ID!) {
person(id: $personId) {
# Basic fields (fast)
# Friend fields (slower)
... @defer {
friends {

Note: in order to use @defer in a React Native application, additional configuration is required. See the React Native docs for more information.

For more information about the @defer , check out the @defer docs.


If your uses , the local-only of that query can provide the values of those variables.

To do so, you apply the @export(as: "variableName") , like so:

query CurrentAuthorPostCount($authorId: Int!) {
currentAuthorId @client @export(as: "authorId")
postCount(authorId: $authorId)

In the above, the result of the local-only currentAuthorId is used as the value of the $authorId that's passed to postCount.

You can do this even if postCount is also a local-only (i.e., if it's also marked as @client).

For more information and other considerations when using the @export , check out the local-only fields docs.

Since 3.8.0

The @nonreactive can be used to mark or spreads and is used to indicate that changes to the data contained within the subtrees marked @nonreactive should not trigger rerendering. This allows parent components to fetch data to be rendered by their children without rerendering themselves when the data corresponding with marked as @nonreactive change.

Consider an App component that fetches and renders a list of ski trails:

const TrailFragment = gql`
fragment TrailFragment on Trail {
const ALL_TRAILS = gql`
query allTrails {
allTrails {
...TrailFragment @nonreactive
function App() {
const { data, loading } = useQuery(ALL_TRAILS);
return (
<h2>Ski Trails</h2>
{data? => (
<Trail key={} id={} />

The Trail component renders a trail's name and status and allows the user to execute a to toggle the status of the trail between "OPEN" and "CLOSED":

const Trail = ({ id }) => {
const [updateTrail] = useMutation(UPDATE_TRAIL);
const { data } = useFragment({
fragment: TrailFragment,
from: {
__typename: "Trail",
return (
<li key={id}>
{} - {data.status}
checked={data.status === "OPEN" ? true : false}
onChange={(e) => {
variables: {
trailId: id,
status: ? "OPEN" : "CLOSED",

Notice that the Trail component isn't receiving the entire trail object via props, only the id which is used along with the to create a live binding for each trail item in the cache. This allows each Trail component to react to the cache updates for a single trail independently. Updates to a trail's status will not cause the parent App component to rerender since the @nonreactive is applied to the TrailFragment spread, a that includes the status .

Error handling
Edit on GitHubEditForumsDiscord

© 2024 Apollo Graph Inc.

Privacy Policy