An LWC has five lifecycle hooks — callbacks the framework invokes at well-defined phases of a component’s existence. Knowing which one to use is half the battle in writing correct components.
The five hooks
| Hook | Fires when | Typical use |
|---|---|---|
constructor() | The component instance is created | Initialise primitive fields. Don’t touch the DOM here. |
connectedCallback() | The component is inserted into the DOM | Subscribe to events, kick off imperative Apex, set up LMS |
renderedCallback() | Every time the component finishes rendering | Read/manipulate child DOM nodes; integrate third-party libs |
disconnectedCallback() | The component is removed from the DOM | Unsubscribe, clear timers, release resources |
errorCallback(error, stack) | A descendant throws an unhandled error | Log, show a friendly message, bubble to monitoring |
A worked example
import { LightningElement } from 'lwc';
import { subscribe, unsubscribe, MessageContext } from 'lightning/messageService';
import { wire } from 'lwc';
import MY_CHANNEL from '@salesforce/messageChannel/MyChannel__c';
export default class OrderPanel extends LightningElement {
@wire(MessageContext) ctx;
subscription = null;
constructor() {
super();
// Field initialisation only — no this.template access yet.
}
connectedCallback() {
// Subscribe once, when we enter the DOM.
this.subscription = subscribe(this.ctx, MY_CHANNEL,
(msg) => this.handleMessage(msg));
}
renderedCallback() {
// Fires after every render. Guard against repeated work.
if (this.chartInitialised) return;
this.chartInitialised = true;
// ... initialise a charting library against this.refs.canvas
}
disconnectedCallback() {
unsubscribe(this.subscription);
}
errorCallback(error, stack) {
console.error('OrderPanel descendant error', error, stack);
}
}
The traps you should call out in an interview
1. Don’t query the DOM in constructor().
The shadow tree isn’t attached yet. this.template.querySelector(...) returns null. Move that logic to renderedCallback() or connectedCallback().
2. renderedCallback() runs more than once.
It fires after the initial render and after every subsequent re-render. If you initialise a chart library inside it without a guard flag, you’ll initialise it dozens of times. The idiomatic pattern:
renderedCallback() {
if (this.hasRendered) return;
this.hasRendered = true;
// one-time setup
}
3. Setting reactive state in renderedCallback() causes infinite loops.
If a state change triggers a re-render, and the re-render triggers the state change, your tab will freeze. Use a guard, or move the logic to a different hook.
4. errorCallback() only catches errors in descendants.
It does not catch errors in the component itself or in its own event handlers. For those, wrap critical code in try/catch directly.
5. There is no beforeRender or willUnmount.
LWC deliberately keeps the lifecycle small. If you find yourself wanting one, you usually want a getter or a different hook.
Render order in a tree
For a parent with a child:
- Parent
constructor→ ParentconnectedCallback→ Childconstructor→ ChildconnectedCallback→ ChildrenderedCallback→ ParentrenderedCallback.
The takeaway: children render before their parent’s renderedCallback fires, so the parent can safely query into the child DOM at that point.
What interviewers want to hear
Connect each hook to a real use case rather than reciting the list. Mention the renderedCallback guard pattern and the infinite-loop trap — they’re the questions interviewers ask as follow-ups when they want to filter copy-paste candidates.
Verified against: LWC Developer Guide — Lifecycle Hooks. Last reviewed 2026-05-17 for Spring ‘26 release.