Events Best Practices

We recommend following these best practices when working with events.

CustomEvent.detail

To communicate data to elements in the same shadow tree, don’t add myProperty into event.detail. The consumer of the event can use the event.target.myProperty.

To communicate data to elements that aren’t in the same shadow tree, use event.detail. In these cases, event.target.* doesn’t work because the real target isn’t visible to the listener. (When an event bubbles up the DOM, if it crosses the shadow boundary, the value of Event.target changes to match the scope of the listener. The event is retargeted so the listener can’t see into the shadow tree of the component that dispatched the event.)

If you do use detail, use primitive types. JavaScript passes all data types by reference except for primitives. If a component includes an object in its detail property, any listener can mutate that object without the component’s knowledge, which is a bad thing!

It is possible to avoid leaking internal state when using a non-primitive type. Before you add data to the detail property, copy it to a new object or array. Copying the data to a new object ensures that you’re sending only the data you want, and that the receiver can’t mutate your data.

Don’t include the non-primitive from @api or @wire in detail. These values are wrapped in a read-only membrane. In IE 11, when crossing the LWC to Aura bridge, the read-only membrane is lost, which means that mutation can occur.

Event Propagation

Use events configured with bubbles: false and composed: false because they're the least disruptive. These events don’t bubble up through the DOM and don’t cross the shadow boundary.

Bubbling and composed events are not recommended because they bubble up the entire DOM tree, across shadow boundaries, and through parent components (unless stopped). If you configure an event with bubbles: true and composed: true, the event type becomes part of the component’s public API. It also forces the consuming component and all of its ancestors to include the event as part of their APIs. It's a big API contract to sign up for. If you do use this configuration, the event type should be globally unique.

See Also