How to Call Apex from a Lightning Web Component (with Examples)
A practical guide to calling Apex from LWC — the @wire decorator vs imperative calls, with code examples and tips on caching, errors and performance.
Calling Apex from a Lightning Web Component is one of the first things every LWC developer learns — and one of the easiest to get subtly wrong. There are two ways to do it, and choosing the right one matters for performance and correctness. Here is how each works.
Step 1: expose an Apex method
Your Apex method must be static and annotated with @AuraEnabled. Add cacheable=true for read-only methods so the platform can cache the result.
public with sharing class AccountController {
@AuraEnabled(cacheable=true)
public static List<Account> getAccounts() {
return [SELECT Id, Name FROM Account ORDER BY Name LIMIT 50];
}
}Step 2a: the @wire approach
Use @wire for cacheable, reactive reads. The component re-renders automatically when the data or a reactive parameter changes — ideal for displaying records.
import { LightningElement, wire } from 'lwc';
import getAccounts from '@salesforce/apex/AccountController.getAccounts';
export default class AccountList extends LightningElement {
@wire(getAccounts)
accounts;
}Step 2b: the imperative approach
Call Apex imperatively when you need control over timing — for example on a button click, or when the method changes data (which cannot be cacheable).
import getAccounts from '@salesforce/apex/AccountController.getAccounts';
async handleClick() {
try {
this.accounts = await getAccounts();
} catch (error) {
this.error = error;
}
}Which should you use?
- Use @wire for read-only data that should stay reactive and cached
- Use imperative for user-triggered actions or anything that writes data
- Never mark a method cacheable if it performs DML
- Always handle the error case — users notice silent failures
AgentExchange builds production LWC with clean Apex controllers, proper caching and full error handling. If you need custom components built or reviewed, email us.