Mixing Wire and Imperative Apex Calls for the Same Data
“Pick one: reactive wire or imperative call. Mixing them creates ghost data.”
What Happened
I had a datatable component that used @wire to load records and an imperative call to refresh after edits. The wire cached the old data. The imperative call returned the new data. But the wire would re-fire on its own schedule and overwrite the imperative results. Users saw records flickering between old and new values. They thought the app was haunted.
The Wrong Way
// myComponent.js
import { LightningElement, wire } from 'lwc';
import getAccounts from '@salesforce/apex/AccountController.getAccounts';
export default class MyComponent extends LightningElement {
accounts;
@wire(getAccounts)
wiredAccounts({ data }) {
if (data) this.accounts = data; // Wire sets data
}
async handleSave() {
await saveAccount({ acc: this.editedAccount });
// Imperative refresh - but wire will overwrite this later!
this.accounts = await getAccounts();
}
}The Right Way
// myComponent.js
import { LightningElement, wire } from 'lwc';
import { refreshApex } from '@salesforce/apex';
import getAccounts from '@salesforce/apex/AccountController.getAccounts';
export default class MyComponent extends LightningElement {
accounts;
wiredAccountsResult;
@wire(getAccounts)
wiredAccounts(result) {
this.wiredAccountsResult = result; // Store the whole result
if (result.data) {
this.accounts = result.data;
}
}
async handleSave() {
await saveAccount({ acc: this.editedAccount });
// Tell the wire to refresh from server - single source of truth
await refreshApex(this.wiredAccountsResult);
}
}The Lesson
Store the wire result object and use refreshApex() to reload data. Never mix wire and imperative calls for the same dataset.
Enjoyed this? Get more like it.
Glen's Musings — AI, investing, and building things. Occasional. Free.
More LWC Mistakes
Calling querySelector Before the Component Renders
The DOM doesn't exist in connectedCallback. Stop looking for it there.
Read morePainfulMutating Objects Without Triggering Reactivity
LWC tracks property assignment, not deep object mutations.
Read moreAnnoyingCustom Events Not Reaching Parent Components
CustomEvent doesn't bubble or compose by default. Your parent never heard you.
Read more