Native Lifecycle Callbacks for Custom Elements
AVAILABLE API VERSIONS |
---|
Available in LWC API v61.0 and later |
In LWC API v61.0, LWC uses native browser APIs to call component lifecycle callbacks.
To support legacy browsers, LWC API v60.0 and earlier call these hooks using a synthetic polyfill. For backwards compatibility, these earlier versions of the LWC API use the synthetic polyfill in all browsers.
Native lifecycle callbacks align with current browser standards. They enable support for the ElementInternals API and the Form-Associated Custom Elements (FACE) API in LWC. Also, native callbacks fix common memory leaks caused by disconnectedCallback()
firing inconsistently.
In LWC, native browser APIs affect how connectedCallback()
, disconnectedCallback()
, and sometimes renderedCallback()
fire in your components. Beginning in LWC API v61.0, these hooks reflect the following changes.
Say you're firing the event onClick
from connectedCallback()
:
connectedCallback()
triggers when you insert element
into the DOM. You can do this using appendChild()
.
In LWC v61.0 and later:
LWCs only fire connectedCallback()
if they're connected to the DOM. Elements connected to the DOM are inside the document
.
To ensure that connectedCallback()
fires, you have to insert element
into the DOM tree like this:
In LWC v60.0 and earlier:
connectedCallback()
fires regardless of whether or not an element is connected to the DOM. For this example, only appending the element
to the div
still triggers this lifecycle hook.
Say connectedCallback()
throws an error for some component c-app
.
Since the error is fired by connectedCallback()
, you can only it catch it when element
gets inserted into the DOM.
In LWC API v61.0 and later:
When elements are added or removed from the DOM, connectedCallback()
and disconnectedCallback()
dispatch errors globally.
To catch the error on .appendChild()
, you have to use a global error
listener.
Events dispatched in connectedCallback()
and disconnectedCallback()
aren't impacted by this change.
If you're using @lwc/jest-*
, you can call the toThrowInConnectedCallback()
API to handle this logic for you. For more information, check out the @lwc/jest-preset
usage guide.
In LWC API v60.0 and earlier:
connectedCallback()
and disconnectedCallback()
dispatch errors locally, so you can catch the error synchronously on .appendChild()
.
In native shadow only, the order in which these two hooks traverse the DOM tree depends on which version of LWC you're using.
Say you have this DOM tree:
Here's the order in which connectedCallback()
fires in each component.
LWC v61.0 and Later | LWC v60.0 and Earlier |
---|---|
|
|
In the following DOM tree, the <c-parent>
and <c-child>
components are slotted. They aren't part of the shadow roots of their containers.
Here's how renderedCallback()
fires in a different order depending on the LWC version being used.
LWC v61.0 and Later | LWC v60.0 and Earlier |
---|---|
|
|
Say you want to select element
's child component c-child
in shadow DOM. In this sample code, you also log c-child
in the console.
In LWC API v61.0 and later:
To render <c-child>
, you have to append the parent component element
to the DOM.
For this example, append the div
to the document
's body
. The following code logs the <c-child>
component in the console.
If you don't append the div
to the document
, c-child
doesn't render and the console logs null
.
In LWC API v60.0 and earlier:
The child component c-child
gets rendered regardless of whether or not the parent element
is connected to the DOM.
For this example, only appending element
to the div still renders c-child
and the console logs c-child
.
You should put your setup logic in connectedCallback()
and your teardown logic in disconnectedCallback()
. If component data changes, rendereredCallback()
may fire more than once. It also might not fire during list reordering.
Say you have the following for:each
iteration.
The items
array is originally [1, 2, 3, 4]
. Later, items
gets reordered to [3, 4, 2, 1]
.
In LWC API v61.0 and later:
When elements are removed and then re-inserted into the DOM, connectedCallback()
and disconnectedCallback()
fire for each list item component. If the data bindings inside the component change too, renderedCallback()
also fires. renderedCallback()
does not run for any of the component's children.
In this example, the LWC framework removes the items 1
and 2
and re-inserts them at the end of the list. After this reordering, disconnectedCallback()
fires for 1
and 2
. Then, connectedCallback()
fires for both items.
In LWC API v60.0 and earlier:
During reordering, the connectedCallback()
, disconnectedCallback()
, and renderedCallback()
lifecycle callbacks don't fire.
See Also