SfSkills Domains Docs GitHub

Home / lwc / lwc-wire-refresh-patterns

lwc-wire-refresh-patterns

refreshApex, getRecordNotifyChange, and RefreshView API for LWC data refresh: when wired data is stale, forcing re-fetch after imperative DML, cross-component refresh, 2024 RefreshView replacement of getRecordNotifyChange. NOT for @wire basics and reactive params — use lwc/wire-service-patterns. NOT for LDS create/update/delete — use lwc/lwc-lds-writes.

Open the skill folder on GitHub


LWC Wire Refresh Patterns

Activate when an LWC's @wire-provisioned data becomes stale after an imperative DML, child record change, or cross-component event. Salesforce offers several refresh primitives — refreshApex, getRecordNotifyChange (deprecated), the newer RefreshView API, and wire re-provisioning via parameter change — each fits a specific scenario.

Before Starting

Core Concepts

refreshApex(wiredValue)

For custom Apex wires. Hold onto the raw wired value (not the destructured data) and call refreshApex(this._wiredAccounts):

@wire(getAccounts, { filter: '$filter' })
wiredAccounts;

handleRefresh() { return refreshApex(this.wiredAccounts); }

RefreshView API

Refresh signal across the page/view. The publisher side is an event dispatch:

import { RefreshEvent } from 'lightning/refresh';
this.dispatchEvent(new RefreshEvent());

The subscriber side is imperative registration, not a wire. RefreshView is not a wire adapter and cannot be used with @wire. The lightning/refresh module exports four functions plus the event: registerRefreshContainer(), registerRefreshHandler(), unregisterRefreshContainer(), unregisterRefreshHandler(), and RefreshEvent (plus the REFRESH_COMPLETE, REFRESH_COMPLETE_WITH_ERRORS, REFRESH_ERROR status constants).

A leaf component participates by registering a handler in connectedCallback() and tearing it down in disconnectedCallback():

import { LightningElement } from 'lwc';
import { registerRefreshHandler, unregisterRefreshHandler } from 'lightning/refresh';

export default class RefreshHandler extends LightningElement {
    refreshHandlerID;

    connectedCallback() {
        this.refreshHandlerID = registerRefreshHandler(this, this.refreshHandler);
    }

    disconnectedCallback() {
        unregisterRefreshHandler(this.refreshHandlerID);
    }

    refreshHandler() {
        // must return a Promise so the container can await completion
        return refreshApex(this.wiredResult);
    }
}

A container component uses registerRefreshContainer(this, this.refreshContainer) and receives a promise it can inspect against REFRESH_COMPLETE / REFRESH_COMPLETE_WITH_ERRORS / REFRESH_ERROR. Registered handlers are invoked from the container node outward. Note that registerRefreshHandler returns an ID, and it is that ID — not the component — that you pass to unregisterRefreshHandler.

notifyRecordUpdateAvailable (legacy)

import { notifyRecordUpdateAvailable } from 'lightning/uiRecordApi'; — still works; informs LDS that specific records changed.

Wire re-provision by param change

Changing a reactive @wire parameter re-runs the wire automatically. Useful when refresh is triggered by user action that changes context.

Common Patterns

Pattern: refreshApex after imperative DML

async save() {
    await updateAccount({ acc: this.acc });
    await refreshApex(this.wiredAccounts);
}

Pattern: Dispatch RefreshEvent from a child after save

Child modal saves a record → dispatches new RefreshEvent() → parent (or the view) refreshes its wires.

Pattern: Cross-component refresh via Lightning Message Service

Sibling components can't share wired data. Use LMS to publish a "data changed" event; siblings subscribe and call their own refresh.

Decision Guidance

ScenarioRefresh mechanism
Custom Apex wire, same componentrefreshApex(wiredValue)
Standard getRecord, after saveRefreshView (RefreshEvent) or notifyRecordUpdateAvailable
Cross-view, global refreshRefreshEvent at the app-level listener
Sibling components needing refreshLightning Message Service + per-component refresh
Param-driven context changeReassign reactive @wire param
  1. Identify the wire adapter — custom Apex vs UI API.
  2. For custom Apex: store the raw wired value; call refreshApex on it.
  3. For UI API: dispatch RefreshEvent or call notifyRecordUpdateAvailable.
  4. For sibling coordination: wire LMS; subscribe and refresh per-component.
  5. Avoid param-nulling hacks.
  6. Test refresh flows with Jest (mock refreshApex + wire adapters).
  7. Document refresh ownership — which component is responsible for triggering refresh.

Review Checklist

Salesforce-Specific Gotchas

  1. refreshApex requires the RAW wired value, not the destructured data. Store wiredFoo (full object) not wiredFoo.data.
  2. getRecordNotifyChange is deprecated. Migrate to RefreshView + notifyRecordUpdateAvailable.
  3. Reassigning @track data to itself does NOT refresh wires. Wires re-run only when reactive params change or explicit refresh is invoked.

Output Artifacts

ArtifactDescription
Refresh pattern selectionPer wire / per trigger mapping
LMS channel for refresh signalsCross-component plumbing
Migration planLegacy getRecordNotifyChange → RefreshView

Package files