Custom Elements lifecycle

Slap yourself if

You think custom elements behave like framework components or assume connectedCallback runs once.

Why this exists

Because many engineers ship Custom Elements with subtle lifecycle bugs, assuming a React-like model where mounting, updating, and unmounting are cleanly separated.

Mental model

Custom Elements lifecycle is DOM-driven, not state-driven. Callbacks reflect node attachment and attribute mutation, not component intent.

  • The browser upgrades an element when its definition becomes available.
  • Constructor runs at upgrade time, not insertion time.
  • connectedCallback and disconnectedCallback fire based on DOM attachment.
  • attributeChangedCallback fires synchronously on observed attribute mutations.
  • Performing DOM reads or writes in the constructor.
  • Assuming connectedCallback is equivalent to mount.
  • Leaking listeners by misusing disconnectedCallback.
  • Treating attributeChangedCallback as a state update hook.

Custom Elements expose DOM-driven lifecycle callbacks that reflect attachment and attribute mutation, not component mounting or rendering phases.

  • Maps callbacks directly to React lifecycle methods.
  • Assumes a single mount/unmount cycle.
  • Ignores upgrade timing.
  • Uses constructor for side effects.

Deep dive

Requires Pro

Premium deep dives include more internals, more scars.

Upgrade timing and constructor traps

Why connectedCallback is not a mount hook

Attribute changes are synchronous and blunt

Lifecycle misuse and silent leaks

How lifecycle explanations reveal shallow understanding