Data Guidelines

The easiest way to work with Salesforce data is to use base Lightning components built on Lightning Data Service. 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. Finally, if 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 GraphQL wire adapter 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.

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, to refresh the data, call the method and then call notifyRecordUpdateAvailable(recordIds) to update the 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.

See Also