Wire Adapters

Read this page in order: wire fundamentals first, Lightning Data Service access patterns second, then message channels and navigation.

getRecord

Usage: Use getRecord to fetch a single record's data from Lightning Data Service.

Guidelines:

  • Define fields as constants at the top of the file
  • Handle both data and error cases
  • Use reactive parameters with $ prefix for dynamic updates

Examples:

import { wire } from 'lwc';
import { getRecord } from 'lightning/uiRecordApi';

const ACCOUNT_FIELDS = [
    'Account.Id',
    'Account.Name',
    'Account.Industry',
    'Account.AnnualRevenue'
];

export default class AccountDetail extends LightningElement {
    @api recordId;

    account;
    error;

    @wire(getRecord, { recordId: '$recordId', fields: ACCOUNT_FIELDS })
    wiredAccount({ error, data }) {
        if (data) {
            this.account = data;
            this.error = undefined;
        } else if (error) {
            this.error = error;
            this.account = undefined;
            this.handleError(error);
        }
    }

    handleError(error) {
        // Handle error appropriately
        console.error('Error loading account:', error);
    }
}

getRecordUi

Usage: Use getRecordUi to fetch record data with UI metadata (layout, picklist values, etc.).

Examples:

import { wire } from 'lwc';
import { getRecordUi } from 'lightning/uiRecordApi';

export default class AccountForm extends LightningElement {
    @api recordId;

    recordUi;
    error;

    @wire(getRecordUi, { recordIds: '$recordId', layoutTypes: 'Full', modes: 'View' })
    wiredRecordUi({ error, data }) {
        if (data) {
            this.recordUi = data.records[this.recordId];
            this.error = undefined;
        } else if (error) {
            this.error = error;
            this.handleError(error);
        }
    }
}

Wire to Apex Methods

Usage: Use @wire with Apex methods for reactive data fetching.

Guidelines:

  • Use cacheable=true for read-only methods when possible
  • Handle errors appropriately
  • Use reactive parameters with $ prefix

Examples:

import { wire } from 'lwc';
import getAccountData from '@salesforce/apex/AccountController.getAccountData';

export default class AccountData extends LightningElement {
    @api recordId;

    accountData;
    error;

    @wire(getAccountData, { accountId: '$recordId' })
    wiredAccountData({ error, data }) {
        if (data) {
            this.accountData = data;
            this.error = undefined;
        } else if (error) {
            this.error = error;
            this.handleError(error);
        }
    }

    handleError(error) {
        // Handle error - show toast, log, etc.
        console.error('Error loading account data:', error);
    }
}

Apex Method (for reference):

@AuraEnabled(cacheable=true)
public static Account getAccountData(Id accountId) {
    return [SELECT Id, Name, Industry FROM Account WHERE Id = :accountId];
}

Wire Error Handling

Guidelines:

  • Always handle wire errors appropriately
  • Provide user feedback for errors (toast notifications, error states)
  • Log errors for debugging
  • Don't leave error states unhandled

Examples:

@wire(getRecord, { recordId: '$recordId', fields: ACCOUNT_FIELDS })
wiredAccount({ error, data }) {
    if (data) {
        this.account = data;
        this.error = undefined;
        this.isLoading = false;
    } else if (error) {
        this.error = error;
        this.account = undefined;
        this.isLoading = false;
        this.handleWireError(error);
    }
}

handleWireError(error) {
    // Show toast notification
    this.showToast('Error', 'Failed to load account data', 'error');

    // Log error for debugging
    console.error('Wire error:', error);

    // Set error state for UI
    this.hasError = true;
}

Lightning Data Service

Use this section for LDS-specific guidance that complements the wire fundamentals above.

Choosing getRecord vs getRecordUi

  • Use getRecord when you need specific fields for component logic
  • Use getRecordUi when you also need layout/metadata context (for example dynamic form behavior)
  • Default to getRecord unless metadata is required, because payloads are usually smaller and simpler to consume

Field Access Patterns

Accessing Field Values:

// Good: Access field value with null check
if (data && data.fields && data.fields.Name) {
    this.accountName = data.fields.Name.value;
}

// Good: Use optional chaining (if supported)
this.accountName = data?.fields?.Name?.value;

// Good: Provide default value
this.accountName = data?.fields?.Name?.value || 'Unknown';

Message Channels

Use this section for Lightning Message Service communication patterns. Keep LMS setup, publishing, and subscription logic together here.

MessageContext Pattern

Usage: Use MessageContext with @wire to access the Lightning Message Service context.

Examples:

import { wire } from 'lwc';
import { MessageContext } from 'lightning/messageService';

export default class MessageComponent extends LightningElement {
    @wire(MessageContext)
    messageContext;
}

Publishing Messages

Usage: Use publish to send messages to subscribed components.

Examples:

import { publish } from 'lightning/messageService';
import SELECTED_CHANNEL from '@salesforce/messageChannel/exampleChild__c';

export default class MessagePublisher extends LightningElement {
    @wire(MessageContext)
    messageContext;

    handleClick() {
        if (this.messageContext) {
            publish(this.messageContext, SELECTED_CHANNEL, {
                identifier: this.uniqueId,
                action: 'clicked'
            });
        }
    }
}

Subscribing to Messages

Usage: Use subscribe to listen for messages from other components.

Examples:

import { subscribe, unsubscribe } from 'lightning/messageService';
import SELECTED_CHANNEL from '@salesforce/messageChannel/exampleChild__c';

export default class MessageSubscriber extends LightningElement {
    @wire(MessageContext)
    messageContext;

    subscription;

    connectedCallback() {
        this.subscribeToMessage();
    }

    subscribeToMessage() {
        if (this.messageContext) {
            this.subscription = subscribe(
                this.messageContext,
                SELECTED_CHANNEL,
                (message) => this.handleMessage(message)
            );
        }
    }

    handleMessage(message) {
        // Handle received message
        if (message.identifier === this.targetId) {
            this.handleAction(message.action);
        }
    }

    disconnectedCallback() {
        if (this.subscription) {
            unsubscribe(this.subscription);
        }
    }
}

Message Channel Best Practices

  • Always unsubscribe in disconnectedCallback to prevent memory leaks
  • Check if messageContext exists before publishing/subscribing
  • Use meaningful message payloads with clear structure
  • Document message channel usage in component documentation

Usage: Use NavigationMixin to navigate to different pages in Salesforce.

Examples:

import { NavigationMixin } from 'lightning/navigation';

export default class NavigationComponent extends NavigationMixin(LightningElement) {
    handleNavigateToRecord() {
        this[NavigationMixin.Navigate]({
            type: 'standard__recordPage',
            attributes: {
                recordId: this.recordId,
                actionName: 'view'
            }
        });
    }

    handleNavigateToObjectHome() {
        this[NavigationMixin.Navigate]({
            type: 'standard__objectPage',
            attributes: {
                objectApiName: 'Account',
                actionName: 'home'
            }
        });
    }

    handleNavigateToWebPage() {
        this[NavigationMixin.Navigate]({
            type: 'standard__webPage',
            attributes: {
                url: 'https://example.com'
            }
        });
    }

    handleGenerateUrl() {
        this[NavigationMixin.GenerateUrl]({
            type: 'standard__recordPage',
            attributes: {
                recordId: this.recordId,
                actionName: 'view'
            }
        }).then((url) => {
            // Use generated URL
            window.open(url, '_blank');
        });
    }
}

Common Navigation Types:

  • standard__recordPage - Navigate to a record detail page
  • standard__objectPage - Navigate to an object's home/list view
  • standard__webPage - Navigate to an external URL
  • standard__namedPage - Navigate to a named page
  • standard__home - Navigate to the home page

Examples:

// Navigate to record page
this[NavigationMixin.Navigate]({
    type: 'standard__recordPage',
    attributes: {
        recordId: '001xx000003DGbQAAW',
        actionName: 'view'
    }
});

// Navigate to object home
this[NavigationMixin.Navigate]({
    type: 'standard__objectPage',
    attributes: {
        objectApiName: 'Account',
        actionName: 'home'
    }
});

// Navigate to external URL
this[NavigationMixin.Navigate]({
    type: 'standard__webPage',
    attributes: {
        url: 'https://example.com'
    }
});
  • Use NavigationMixin for all navigation within Salesforce
  • Use GenerateUrl when you need the URL for external use (e.g., opening in new tab)
  • Handle navigation errors appropriately
  • Provide user feedback for navigation actions

Change History

Version 1.0 - 2026-03-26

  • Added initial version history tracking for this document.

Last Updated: 2026-03-26 Version: 1.0