getRecords

Use this wire adapter to get data for a batch of records at once. You can request multiple objects or different record types.

Syntax 

1import { LightningElement, wire } from 'lwc';
2import { getRecords } from 'lightning/uiRecordApi';
3
4@wire(getRecords, { records: [ { recordIds: string[], fields: string[] } ] })
5propertyOrFunction
6
7@wire(getRecords, { records: [ { recordIds: string[], fields: string[], optionalFields?: string[] } ] })
8propertyOrFunction

User Interface API Resource 

1GET /ui-api/records/batch/{recordIds}

The getRecords wire adapter uses this User Interface API resource, but doesn’t support all its parameters.

Parameters 

Parameter NameTypeDescriptionRequired?
recordsObjectAn array of record data, which can be across multiple objects or record types.Yes

records has several properties.

records PropertyTypeDescriptionRequired?
recordIdsString[](At least one required) The ID of records to fetch from supported objects.Yes
fieldsString[]An array of fields to return. If the context user doesn’t have access to a field, an error is returned. If you’re not sure whether the context user has access to a field and you don’t want the request to fail if they don’t, use the optionalFields parameter.
Specify field names in the format ObjectApiName.FieldName or ObjectApiName.JunctionIdListName. Polymorphic fields aren’t supported. Including a polymorphic field in fields can result in an invalid field error.
optionalFieldsString[]An array of optional field names. If a field is accessible to the context user, it’s included in the response. If a field isn’t accessible to the context user, it isn’t included in the response, but it doesn’t cause an error. Specify field names in the format ObjectApiName.FieldName or ObjectApiName.JunctionIdListName.

Read the data that’s returned by the wire adapter using a property or function.

propertyOrFunction—A private property or function that receives the stream of data from the wire service.

  • If a property is decorated with @wire, the results are returned to the property’s data property or error property.
  • If a function is decorated with @wire, the results are returned in an object with a data property and an error property.

Returns 

Usage 

To get data for a single record, use getRecord instead.

To filter by criteria and work with dynamic record IDs easily, consider using the GraphQL wire adapter instead.

Tip

This example loads several records using the record IDs. Replace the recordIds values with your own.

1import { LightningElement, wire } from "lwc";
2import { getRecords } from "lightning/uiRecordApi";
3import NAME_FIELD from "@salesforce/schema/User.Name";
4import EMAIL_FIELD from "@salesforce/schema/User.Email";
5
6export default class GetRecordsExample extends LightningElement {
7  @wire(getRecords, {
8    records: [
9      {
10        recordIds: ["005XXXXXXXXXXXXXXX", "005XXXXXXXXXXXXXXX"],
11        fields: [NAME_FIELD],
12        optionalFields: [EMAIL_FIELD],
13      },
14    ],
15  })
16  wiredRecords;
17}

Alternatively, you can request for records across multiple objects.

1import { LightningElement, wire } from "lwc";
2import { getRecords } from "lightning/uiRecordApi";
3import USER_NAME_FIELD from "@salesforce/schema/User.Name";
4import USER_EMAIL_FIELD from "@salesforce/schema/User.Email";
5import ACCOUNT_NAME_FIELD from "@salesforce/schema/Account.Name";
6
7export default class GetRecordsExample extends LightningElement {
8  @wire(getRecords, {
9    records: [
10      {
11        recordIds: ["005XXXXXXXXXXXXXXX"],
12        fields: [USER_NAME_FIELD],
13        optionalFields: [USER_EMAIL_FIELD],
14      },
15      {
16        recordIds: ["001XXXXXXXXXXXXXXX"],
17        fields: [ACCOUNT_NAME_FIELD],
18      },
19    ],
20  })
21  wiredRecords;
22}

To work with dynamic record IDs, consider using the GraphQL wire adapter instead.

If you use the getRecords wire adapter with dynamic record IDs, we recommend that you create a parameterObject array that you can push your record parameters to as a single property. Using an array enables you to define record IDs and fields for multiple objects.

For example, you can retrieve contact IDs by account via an Apex controller and then pass them to the parameterObject array. You can also pass in your record parameters from a parent component to a child component that initializes the array.

When you call the wire adapter, the User Interface API composes a SOQL query for the request. This SOQL query has a limit of 100k characters. If you expect to exceed this limit, we recommend splitting the query into multiple queries and running them in batches.

Note

This example shows how you can retrieve contact and user records on an account. It assumes that you retrieve the contacts on an account using an Apex controller.

1public with sharing class ContactsController {
2  @AuraEnabled(cacheable=true)
3  public static List<Contact> getContactsByAccount(Id accountId) {
4    return [
5            SELECT Id
6            FROM Contact
7            WHERE AccountId = :accountId
8    ];
9  }
10}

In your JavaScript, set up the parameterObject array to define record IDs and fields for the contact and user records. Then, pass in the $parameterObject dynamic variable to the getRecords wire adapter.

1import { LightningElement, api, wire, track } from "lwc";
2import getContacts from "@salesforce/apex/ContactsController.getContactsByAccount";
3import CONTACT_NAME_FIELD from "@salesforce/schema/Contact.Name";
4import USER_NAME_FIELD from "@salesforce/schema/User.Name";
5import userId from "@salesforce/user/Id";
6
7export default class DynamicIDExample extends LightningElement {
8  @api recordId; //current Account's Id
9  contacts = [];
10  @track filteredData = [];
11  parameterObject;
12
13  @wire(getContacts, { accountId: "$recordId" })
14  retrievedContacts({ error, data }) {
15    if (data) {
16      this.contacts = data;
17      if (this.contacts.length > 0) {
18        this.parameterObject = [];
19        this.contacts.forEach((contact) => {
20          this.parameterObject.push({
21            recordIds: [contact.Id],
22            fields: [CONTACT_NAME_FIELD],
23          });
24        });
25        this.parameterObject.push({
26          recordIds: [userId],
27          optionalFields: [USER_NAME_FIELD],
28        });
29      } else if (error) {
30        this.contacts = undefined;
31      }
32    }
33  }
34
35  @wire(getRecords, { records: "$parameterObject" })
36  wiredRecords({ error, data }) {
37    if (data) {
38      data.results.forEach((record) => {
39        this.filteredData.push({
40          Name: record.result.fields.Name.value,
41          Id: record.result.id,
42        });
43      });
44    } else if (error) {
45      console.log("error: ", error);
46    }
47  }
48}

When you use this component on an account record page, it renders a list of contact names that are associated on the account and the username of the account owner.

1<template>
2  <lightning-card title="DynamicIDExample" icon-name="standard:contact">
3    <div class="slds-var-m-around_medium">
4      <template lwc:if={filteredData}>
5        <template for:each={filteredData} for:item="record">
6          <p key={record.Id}>{record.Name}</p>
7        </template>
8      </template>
9      <template lwc:elseif={errors}>
10        <c-error-panel errors={errors}></c-error-panel>
11      </template>
12    </div>
13  </lightning-card>
14</template>

The lwc-recipes repo has several examples that demonstrate getRecords usage. Look for components that start with wireGetRecords, such as wireGetRecordsDifferentTypes component.

Tip

Error Handling 

getRecords returns errors in the error property. For example, you get a 400 Bad Request error if you pass in an invalid field name to the fields or optionalFields array.

1{
2  "status": 400,
3  "body": {
4    "message": "Expected '.' in all qualified names: badFieldName is invalid",
5    "statusCode": 400,
6    "errorCode": "ILLEGAL_QUERY_PARAMETER_VALUE",
7    "id": "1369078084"
8  },
9  "headers": {},
10  "ok": false,
11  "statusText": "Bad Request",
12  "errorType": "fetchResponse"
13}

If the response status returns a 200 success code but a subrequest returns a statusCode of 400 or another non-200 error code, the network response returns hasErrors:true, but this property isn’t returned as part of data.

To identify errors in a subrequest, check the data.results object.

  • If the subrequest returns a 200 success code, the results.result object contains record data with the requested fields.
  • If the subrequest returns a non-200 error code or 400 error code, the results.result object contains the errorCode and message properties.

For example, you get an overall 200 success code if you request two records - a record with valid fields and a record with an invalid ID. Although the subrequest for the first record is returned with a 200 success code, the subrequest for the second record is returned with a 400 error code.

1{
2  "results": [
3    {
4      "statusCode": 200,
5      "result": {
6        "apiName": "Contact",
7        "childRelationships": {},
8        "fields": {
9          "Name": {
10            "displayValue": null,
11            "value": "Sean Forbes"
12          },
13          "Email": {
14            "displayValue": null,
15            "value": "sean@edge.com"
16          }
17        },
18        "id": "0031a00000527vwAAA",
19        "lastModifiedById": "0051a000000GqXfAAK",
20        "lastModifiedDate": "2015-06-17T22:17:58.000Z",
21        "recordTypeId": "012000000000000AAA",
22        "recordTypeInfo": null,
23        "systemModstamp": "2015-06-17T22:17:58.000Z"
24      }
25    },
26    {
27      "statusCode": 400,
28      "result": [
29        {
30          "errorCode": "UNKNOWN_EXCEPTION",
31          "message": "Record ID is malformed: 0031a00000527vxAAb"
32        }
33      ]
34    }
35  ]
36}

To display errors, you can use toasts provided by the lightning/platformShowToastEvent module with a Promise that includes then() and catch() blocks.

1import { LightningElement, api, wire } from "lwc";
2import { ShowToastEvent } from "lightning/platformShowToastEvent";
3import { getRecords } from "lightning/uiRecordApi";
4
5const FIELDS = ["Contact.Name", "Contact.Phone"];
6
7export default class LoadContact extends LightningElement {
8  @api recordId;
9  contacts;
10  name;
11  phone;
12  @wire(getRecords, {
13    records: [
14      {
15        recordIds: ["005XXXXXXXXXXXXXXX", "005XXXXXXXXXXXXXXX"],
16        fields: FIELDS,
17      },
18    ],
19  })
20  wiredRecord({ error, data }) {
21    if (error) {
22      let message = "Unknown error";
23      if (Array.isArray(error.body)) {
24        message = error.body.map((e) => e.message).join(", ");
25      } else if (typeof error.body.message === "string") {
26        message = error.body.message;
27      }
28      this.dispatchEvent(
29        new ShowToastEvent({
30          title: "Error loading contacts",
31          message,
32          variant: "error",
33        }),
34      );
35    } else if (data) {
36      this.contacts = data;
37      this.name = this.contacts.results[1].result.fields.Name.value;
38      this.phone = this.contacts.results[1].result.fields.Phone.value;
39    }
40  }
41}

Release Preview

This release is in preview. Features described here don't become generally available until the latest general availability date that Salesforce announces for this release. Before then, and where features are noted as beta, pilot, or developer preview, we can't guarantee general availability within any particular time frame or at all. Make your purchase decisions only on the basis of generally available products and features.