# GraphQL Wire Adapter Best Practices

When creating queries for your GraphQL wire adapter, follow these best practices to get the most out of GraphQL API for your LWC development.

## Query Only the Data You Need

Here’s where the power of GraphQL shines. You can write a query that satisfies your data needs and gives you exactly what you asked for, nothing more and nothing less. Writing a brief query that satisfies your data requirements makes the return result predictable, while ensuring that your query remains performant.

Use the `first` argument to limit the number of results, and [paginate your results](/docs/platform/graphql/guide/graphql-wire-lwc-paginate.md) with the `after` argument. The default is 10.

In this example, including the `totalCount` field makes the query look up all existing records, even though it returns only the first 5.

```javascript
//simpleGQL.js
import { LightningElement, wire } from "lwc";
import { gql, graphql } from "lightning/graphql";
export default class SimpleGQL extends LightningElement {
  results;
  errors;

  @wire(graphql, {
    query: gql`
      query AccountWithName {
        uiapi {
          query {
            Account(first: 5) {
              totalCount
              edges {
                node {
                  Id
                  Name {
                    value
                  }
                }
              }
            }
          }
        }
      }
    `,
  })
  graphqlQueryResult({ data, errors }) {
    if (data) {
      this.results = data.uiapi.query.Account.edges.map((edge) => edge.node);
    }
    this.errors = errors;
  }
}
```

:::tip
Requesting `totalCount` can have performance implications for large or complex queries.
:::

## Use GraphQL Variables for Arguments

Using variables makes your query reusable with LWC’s reactivity feature, which means that your query fetches the data only if any of the variable values changed.

Using variables ensures that your query results reflect the arguments being used. It also helps improve performance so that the client framework understands that the query itself hasn’t changed and it can skip parsing and revalidating the query.

The `$minAmount` GraphQL variable enables the component to set and change the minimum amount.

```javascript
@wire(graphql, {
        query: gql`
            query bigAccounts($minAmount: Currency) {
                uiapi {
                    query {
                    Account(where: { AnnualRevenue: { gte: $minAmount } }) {
                        edges {
                            node {
                                Id
                                Name {
                                    value
                                }
                                AnnualRevenue {
                                    displayValue
                                }
                         }
                     }
                 }
             }
          }
       }`,
        variables: '$variables', //Use a getter function to make the variables reactive
    })
    graphqlQueryResult({ data, errors }) {
        if (data) {
            this.records = data.uiapi.query.Account.edges.map(edge => edge.node);
        }
        this.errors = errors;
    }
```

For more information, see [Make Your Variables Reactive](/docs/platform/graphql/guide/graphql-wire-lwc-reactive.md).

## Delay Query Execution

To delay your query from executing, such as for testing or if you’re working with multiple queries, use a getter and pass in the query using a variable like `query: '$recordQuery'`. For example, delaying the query can be helpful if you’re fetching contacts by account ID and don’t have the account ID when the component loads.

```javascript
@wire(graphql, { query: '$recordQuery', variables: '$variables' }) ...;


get recordQuery() {
  return this.recordId ? gql`thequery` : undefined;
}

get variables() {
  return { this.recordId }
}
```

:::note
If `this.recordId` is `undefined` during the initial page load, `get recordQuery()` returns `undefined`. Most Salesforce mobile environments, like Field Service and the Salesforce mobile app, can’t prefetch `undefined` queries.
:::

In this example, the `accountId` isn’t reactive to changes.

```javascript
// Don't do this
@wire(graphql, { query: '$query', variables: { accountId: this.accountId }) ;
```

In some cases, you don’t have the account ID when the component loads, for example:

- You expect the user to select an account, which then sets the account ID
- You set the account ID depending on which account record page displays

To delay query execution, make your query reactive by updating the `query` and `variables` parameters like in the next example.

This example queries the associated contacts on an account record page that’s currently displayed. The AccountId field value on the Contact object is provided by `@api recordId`, which makes [a component aware of its record context](https://developer.salesforce.com/docs/platform/lwc/guide/use-record-context.md).

```javascript
// accountIdExample.js
import { LightningElement, wire, api } from "lwc";
import { gql, graphql } from "lightning/graphql";

export default class AccountIdExample extends LightningElement {
  contacts;
  errors;
  @api recordId;

  @wire(graphql, {
    query: "$accountQuery",
    variables: "$accountData",
  })
  contactsQueryResult({ data, errors }) {
    if (data) {
      this.contacts = data.uiapi.query.Contact.edges.map((edge) => edge.node);
    }

    if (errors) {
      this.contactsError = errors;
    }
  }

  get accountQuery() {
    // Send a request to the server only if recordId is provided.
    if (!this.recordId) return undefined;

    return gql`
      query contactsOnAccount($recordId: ID!) {
        uiapi {
          query {
            Contact(where: { AccountId: { eq: $recordId } }) {
              edges {
                node {
                  Id
                  Name {
                    value
                  }
                }
              }
            }
          }
        }
      }
    `;
  }

  get accountData() {
    return {
      recordId: this.recordId,
    };
  }
}
```

The HTML template looks like this.

```html
<!-- accountIdExample.html -->
<template>
  <lightning-card title="Account Id Example" icon-name="standard:contact">
    <div class="slds-var-m-around_medium">
      <template lwc:if={contacts}>
        <template for:each={contacts} for:item="contact"> {contact.Name.value} </template>
      </template>
    </div>
  </lightning-card>
</template>
```

## Dynamically Construct Queries at Run Time

Dynamically generate queries in the wire adapter at run time to support component state or user input. To dynamically construct your query, use JavaScript string interpolation inside the `gql` tagged template literal. Dynamic query construction in the wire adapter is available in API v65.0 and later and requires the `lightning/graphql` LWC module.

In this example, `${this.objectName}` represents the dynamic part of the query that’s resolved at run time.

```javascript
import { LightningElement, track, wire } from "lwc";
import { gql, graphql } from "lightning/graphql";

export default class DynamicGraphQLQuery extends LightningElement {
  @track objectName = "Account";

  get resolvedQuery() {
    return gql`
      query {
        uiapi {
          query {
            ${this.objectName} {
              edges {
                node {
                  Id
                  Name
                }
              }
            }
          }
        }
      }
    `;
  }

  @wire(graphql, { query: "$resolvedQuery", variables: {} })
  result;

  get data() {
    return this.result?.data ? JSON.stringify(this.result.data, null, 2) : "";
  }
}
```

Unlike static queries, referential integrity isn’t automatically preserved for dynamically generated queries. You must manually resolve any compilation errors in LWC components caused by renamed or deleted entities or fields.

## Execute Multiple Queries

Send multiple queries in one operation if you want to request record data for multiple objects. Combining multiple queries can help prevent unnecessary requests to the server. For example, send your query in a separate call if the query depends on a field or value from an earlier query.

Alternatively, work with [semi-joins or auto-joins](/docs/platform/graphql/guide/filter-parent.md) to query records with parent and child relationships.

## Work with Parent and Child Relationships

You can specify a parent or child relationship in your query for the GraphQL wire adapter.
Objects can have children relationships to the same object, just like a parent account can have child accounts. Some objects have children relationships to other objects. For example, accounts have child relationships to assets, cases, and contacts among other objects.

The GraphQL API schema provides details of parent-child relationships. For example, the Account field is a `parentRelationship` type on the Contact object. Similarly, the Cases field is a `childRelationship` type on the Contact object.

```sfdocs-code {"lang":"graphql", "title": "Query contacts and their associated cases and accounts", "src": "" }
query contacts {
  uiapi {
    query {
      Contact {
        edges {
          node {
            Cases {
              edges {
                node {
                  Subject { value }
                  Status { value }
                  Priority { value }
                }
              }
            }
            Account {
              Name { value }
            }
          }
        }
      }
    }
  }
}
```

For more information, see [Relationship Filters](/docs/platform/graphql/guide/filter-parent.md).

## Use Aliases with Custom Objects and Fields

Salesforce automatically understands references to objects and fields within your GraphQL queries and applies referential integrity to those references. If your GraphQL query references a custom entity or field and that entity or field is renamed, Salesforce updates your GraphQL query to use the new name. While this update prevents your query from failing at run time, it also changes the shape of the data returned from the query.

To protect against unintentional change of the data shape, we recommend that you add GraphQL aliases to any custom object and field names in your GraphQL query that could change. Adding aliases preserves the names used for these objects and fields in the GraphQL result, while still allowing Salesforce’s referential integrity mechanisms to work correctly. Aliases ensure that your component remains valid and prevents any run-time errors in the future.

:::note
We recommend that you add the alias to any custom object and field during development time, which ensures that changes made to these objects in a subscriber org won’t break the component.
Using an alias isn’t supported for standard objects and fields.
:::

Let’s say you are querying a custom object and a custom field like this.

```javascript
//aliasGQL.js
import { LightningElement, wire } from "lwc";
import { gql, graphql } from "lightning/graphql";
export default class AliasGQL extends LightningElement {
  results;
  errors;

  @wire(graphql, {
    query: gql`
      query AccountWithName {
        uiapi {
          query {
            Custom_object__c(first: 5) {
              edges {
                node {
                  Id
                  Object_name__c {
                    value
                  }
                }
              }
            }
          }
        }
      }
    `,
  })
  graphqlQueryResult({ data, errors }) {
    if (data) {
      this.results = data.uiapi.query.Custom_object__c.edges.map((edge) => edge.node);
    }
    this.errors = errors;
  }
}
```

Add aliases to all custom objects and fields used in your query during development, before you publish a managed package. See [Use a Namespace and Alias in Managed Packages](/docs/platform/graphql/guide/graphql-wire-lwc-namespace.md).

```javascript
//aliasUpdateGQL.js
import { LightningElement, wire } from "lwc";
import { gql, graphql } from "lightning/graphql";
export default class AliasGQL extends LightningElement {
  results;
  errors;

  @wire(graphql, {
    query: gql`
      query AccountWithName {
        uiapi {
          query {
            Custom_object: Custom_object__c(first: 5) {
              edges {
                node {
                  Id
                  Object_name: Object_name__c {
                    value
                  }
                }
              }
            }
          }
        }
      }
    `,
  })
  graphqlQueryResult({ data, errors }) {
    if (data) {
      this.results = data.uiapi.query.Custom_object.edges.map((edge) => edge.node);
    }
    this.errors = errors;
  }
}
```

If a subscriber org or your team member changes the object or field name, updating `Custom_object__c` to `Custom_object2__c`, and `Object_name__c` to `Object_name2__c`, your component preserves its referential integrity.

```javascript
//aliasUpdateGQL.js
import { LightningElement, wire } from "lwc";
import { gql, graphql } from "lightning/graphql";
export default class AliasUpdateGQL extends LightningElement {
  results;
  errors;

  @wire(graphql, {
    query: gql`
      query AccountWithName {
        uiapi {
          query {
            Custom_object: Custom_object2__c(first: 5) {
              edges {
                node {
                  Id
                  Object_name: Object_name2__c {
                    value
                  }
                }
              }
            }
          }
        }
      }
    `,
  })
  graphqlQueryResult({ data, errors }) {
    if (data) {
      this.results = data.uiapi.query.Custom_object.edges.map((edge) => edge.node);
    }
    this.errors = errors;
  }
}
```

The wire adapter returns a JSON response that looks like this.

```json
{
  "data": {
    "uiapi": {
      "query": {
        "Custom_object": {
          "edges": [
            {
              "node": {
                "Id": "00X1a00000cR4wuAAC",
                "Object_name": {
                  "value": "My name"
                }
              }
            }, # more data here
          ]
        }
      }
    }
  },
  "errors": []
}
```

## See Also

[GraphQL Wire Adapter Limitations](/docs/platform/graphql/guide/graphql-wire-lwc-limitations.md)
