A deep dive into common mistakes developers make with Lightning Web Components' wire service, public properties (@api), and event handling. Covers why @wire is a subscription rather than a one-time fetch, why mutating wire results or event.detail breaks reactivity, pitfalls like updating wire config in renderedCallback (infinite loops), mixing Apex and LDS caches, misusing refreshApex(), swapping config objects to force re-fetch, and event anti-patterns like inline .bind() calls, capture-phase listeners, and unnecessary bubbles/composed flags. Recommends notifyRecordUpdateAvailable() for cache invalidation and Lightning Message Service as a replacement for the deprecated pubsub module.

11m read timeFrom developer.salesforce.com
Post cover image
Table of contents
Wire service anti-patternsPublic property anti-patternsEvent handling anti-patternsConclusionResourcesAbout the author

Questions this post answers

Why does my Lightning Web Component show stale data even after I update a record through Apex?

Lightning Data Service (LDS) maintains its own cache that is unaware of changes made through imperative Apex calls, so every LDS wire adapter on the page keeps serving the pre-mutation value. Calling notifyRecordUpdateAvailable() after the Apex write completes tells LDS the record is stale, which triggers all subscribed wire adapters to fetch fresh data automatically. daily.dev surfaces practical fixes for LDS cache staleness when Apex and wire adapters disagree.

Why doesn't refreshApex() work when I call it on getRecord in LWC?

refreshApex() only works on wired Apex methods, not on Lightning Data Service adapters like getRecord; calling it there is deprecated and has no reliable effect. LDS manages its own cache automatically for LDS-aware operations, and the correct way to signal a stale record after an out-of-band write is to call notifyRecordUpdateAvailable() instead. developers debugging LWC cache refresh issues can track these caching quirks on daily.dev.

Why does my custom event listener never get removed even though I called removeEventListener with .bind()?

Calling .bind() returns a brand-new function object every time it runs, so passing this.handler.bind(this) to addEventListener and then a separate this.handler.bind(this) call to removeEventListener passes two different functions, meaning the original listener is never removed. Using an arrow function class field, which keeps the same reference, or storing a single bind() result in a property avoids this leak. daily.dev helps developers catch subtle event listener memory leaks like this bind() mismatch.

249 Impressions