The Salesforce Developers website will undergo maintenance on May 29, 2024 from 3:00 a.m. UTC to 10:00 a.m. UTC. The maintenance process may affect the availability of our documentation. Please plan accordingly.

Data Guidelines

The easiest way to work with Salesforce data is to use base Lightning components built on Lightning Data Service (LDS). If you need more flexibility, use a Lightning Data Service wire adapter directly. Each wire adapter provides different data and metadata. The wire service provisions the data and metadata to your component.

Start with the GraphQL wire adapter if you want to send multiple queries in one operation. Finally, if GraphQL and LDS wire adapters aren’t flexible enough, use Apex.

Lightning Data Service supports all custom objects and all the standard objects that User Interface API supports. External objects, person accounts, and custom metadata types are not supported. Lightning Data Service doesn’t incur any API usage calls, but it is subject to general limits like the numbers of records returned.

Lightning Data Service manages data for you; changes to a record are reflected in all the technologies built on it.

The base Lightning components built on Lightning Data Service are lightning-record-form, lightning-record-edit-form, and lightning-record-view-form. They provide a UI to view, create, and edit a record—similar to the record detail page in Salesforce.

Use the lightning-record*form components to:

  • Create a metadata-driven UI or form-based UI similar to the record detail page in Salesforce.
  • Display record values based on the field metadata.
  • Display or hide localized field labels.
  • Display the help text on a custom field.
  • Perform client-side validation and enforce validation rules.

Consider the following guidelines when using the lightning-record*form components.

This component is the easiest way to display a form to create, edit, or view a record. The form switches between view and edit modes automatically when the user begins editing a field. The component uses the object's default record layout with support for multiple columns. It loads all fields in the object's compact or full layout, or only the fields that you specify.

To improve performance, specify fields instead of a layout whenever possible. Specify a layout only when you want the administrator, not the component, to control the fields that are provisioned. The component must handle receiving every field that is assigned to the layout for the context user.

To customize the form display or provide custom rendering of record data, use lightning-record-edit-form (to add or update a record) and lightning-record-view-form (to view a record). lightning-record-edit-form enables you to prepopulate field values using the lightning-input-field component.

See Work with Records Using Base Components.

To create a custom UI or if you don’t need a metadata-driven UI, use a wire adapter.

The lightning/uiGraphQLApi and lightning/ui*Api modules provide the Lightning Data Service (LDS) wire adapters and functions.

The GraphQL wire adapter manages your data using LDS. It provides a single endpoint that lets you query exact fields and objects without Apex. It reduces request payloads and minimizes the number of requests you need to fetch data for users, compared to other LWC wire adapters.

GraphQL can be more performant if you're replacing multiple requests via other wire adapters. When working with a large number of records, the wire adapter's pagination functionality can also help you present your data with ease and efficiency.

With shared caching by Lightning Data Service, field-level security, and user and org permissions, you can use GraphQL wire adapter features in these scenarios:

  • Send multiple queries in one operation
  • Request record data for multiple objects
  • Query records with parent and child relationships
  • Filter by criteria and order query results
  • Work with dynamic record IDs

See GraphQL API for LWC.

To access raw record data so that you can perform business logic or create a form that needs more customization than the LDS base components allow, use @wire to specify the getRecord Lightning Data Service wire adapter.

To display a list of field values, such as a list of contact names, use getListUi.

You can use multiple wire adapters to provision data for multiple records, but each operation is an independent transaction. To work with multiple records in a single transaction, use Apex.

To create, edit, or delete single records, call the createRecord, updateRecord, and deleteRecord functions in the lightning/ui*Api module. Like the LDS wire adapters, to work with multiple records, you can use multiple functions, but each operation is an independent transaction. To work with multiple records in a single transaction, use Apex.

To improve performance, use the wire adapter that returns the least amount of data that your use case requires. For example, the GraphQL wire adapter returns only the data you query. In contrast, the getRecord LDS wire adapter returns child relationships and layout types in addition to the fields you specify.

See Use the Wire Service to Get Data and Create a Record.

If you can’t use a base component, and you can’t use the Lightning Data Service wire adapters or functions, use Apex.

Unlike Lightning Data Service data, Apex data is not managed; you must refresh the data. If Apex data is provisioned via the wire service, refresh it by calling refreshApex(), which uses the wire configuration to get data and update the cache. If your code calls an Apex method imperatively, refresh the data by calling the method and then call notifyRecordUpdateAvailable(recordIds) to update the cache. You only need to call notifyRecordUpdateAvailable() if you expect any relevant data to be updated in the LDS cache.notifyRecordUpdateAvailable() signals to LDS that some records are stale and refreshes those records that are in the LDS cache.

The use of refreshApex to refresh data from non-Apex wire adapters is deprecated. To refresh record data returned by a non-Apex wire adapter, use notifyRecordUpdateAvailable(recordIds) instead.

Use Apex in these scenarios:

  • To work with objects that aren’t supported by User Interface API, like Task and Event.
  • To work with operations that User Interface API doesn’t support, like loading a list of records by criteria (for example, to load the first 200 Accounts with Amount > $1M).
  • To perform a transactional operation. For example, to create an Account and create an Opportunity associated with the new Account. If either create fails, the entire transaction is rolled back.
  • To call a method imperatively, as opposed to via the wire service. You may want to call a method imperatively in response to clicking a button, or to delay loading to outside the critical path. When you call an Apex method imperatively, to refresh the data, invoke the Apex method again.

See Call Apex Methods.

To prevent code complexity and unwanted side-effects, data should flow in one direction, from parent to child. To trigger a mutation, a component should send an event to its parent. Objects passed to a component are read-only. To mutate the data, a component should make a shallow copy of the objects it wants to mutate. It’s important to understand these concepts when working with data. See Data Flow.

Depending on your use case, you could be working with a combination of Apex and Lightning Data Service (LDS) wire adapters. Consider these guidelines when you work with data returned by Apex and LDS.

  • Apex doesn't share a data cache or data store with LDS. Data that you fetch using Apex can be inconsistent with data fetched using LDS wire adapters in both online and offline conditions. For example, your component can behave unexpectedly if it fetches data using Apex and then uses the GraphQL wire adapter to perform a search query on the same data.
  • When using SOQL to get data, use the GraphQL wire adapter when performing a fetch and search query. Using the GraphQL wire adapter consistently for both fetch and search can prevent issues such as fetching Apex data while retrieving a corresponding null value on your GraphQL wire adapter.

See Also