When building applications with Lightning Web Components (LWC), developers need to pass information across components to share state and re-render components. In this post, I’ll share an overview of the different communication patterns along with their perks and use-cases. We’ll look at the three types of exchanges:
- Passing data down the component hierarchy.
- Passing data up the component hierarchy.
- Passing data to components that share no common ancestry.
Passing data down the component hierarchy
There are three techniques for passing data from a parent to a child component; you may either use a public property, a setter or a method. For reference, a child component is a component that’s included in the HTML template of a parent component at design time. At runtime, the child component will be embedded in a sub-DOM tree of the parent component.
Public properties
A public property is the simplest way to receive data in a child component and requires the least amount of code. A public property is exposed by applying the @api
decorator on a class property of a child component. This lets the parent component assign a value to it in two different ways. Either via a custom HTML attribute or dynamically with JavaScript.
Here’s an example of how a parent component updates a childAttribute
public property from a child component. Note how the childAttribute
property name is automatically converted to kebab case (lowercase, dash-separated) when set with an HTML attribute.
Public properties are reactive so the component re-renders whenever one of its public properties is updated. On the downside, you cannot run custom logic when the value changes and the child component should not assign values to its public properties.
See the ApiProperty recipe from our LWC Recipes sample app for an example of a public property.
Public getters and setters
Public getters and setters behave exactly like public properties when used in a parent component. However, they bring additional flexibility to the child component by allowing you to execute custom logic when retrieving or updating a value. Additionally, a child component is able to set values using its own setters.
Another important difference with public properties is that getters and setters don’t provide persistence out of the box. A common pattern to handle that is to use a “private” property prefixed with an underscore to store the value internally in the child component.
Here’s an example of how a parent component uses a childAttribute
public setter from a child component and saves its value in a _childAttribute
property:
See the ApiSetterGetter recipe from LWC Recipes for an example of a public getters and setters.
Public methods
You may call public methods to pass several values to a child component in order to perform an action like a calculation. As opposed to setters, methods allow you to enforce consistency by passing multiple parameters at once.
Here’s an example of how a parent component calls a calculate
public method from a child component:
Unlike public properties or setters, methods are not exposed in the component’s HTML tag. They can only be called with JavaScript. This can be a limitation if you need to call a method in a reactive way (whenever some values change). Likewise, calling a method won’t automatically trigger a re-render on the target component. The component only re-renders if the method modifies properties used in the component’s template.
Methods support asynchronous processing as they can return any type of value including promises.
See the ApiMethod recipe from LWC Recipes for an example of a public method.
Passing data up the component hierarchy
You can pass data from a child component to a parent or ancestor with events. Lightning Web Components relies on DOM events (as defined in the standard DOM specification) to propagate data up the component hierarchy.
Here’s an example of how a child component can dispatch a CustomEvent with a contact ID to a parent component:
You can configure an event’s propagation so that it propagates to ancestor components that are not direct parents of a child component. To do so, you can set the bubbles
attribute when creating the event:
You can also stop the event propagation at any time with Event.stopPropagation().
Check out the “Child-to-Parent” recipes from LWC Recipes for various examples of event firing and handling.
Passing data to components that share no common ancestry
Sometimes you need to send data to components that share no common ancestry. For example, you may need to send data to or from a component hosted in a different region of a Lightning page or in a utility bar. This type of communication can be achieved with the Lightning Message Service or with the pubsub module.
Lightning message service
The Lightning Message Service (LMS) is the preferred solution for communicating between components that aren’t in the same DOM tree. LMS also allows communication between the three Salesforce UI technologies: Lightning Web Components, Aura and Visualforce.
LMS provides a publish/subscribe mechanism that allows for the exchange of messages between components. For the sake of brevity and in order not to duplicate documentation, we won’t dive into the technical details of how to publish and subscribe to Lightning messages – but it requires three key steps:
- Declare a message channel using the
LightningMessageChannel
metadata type. - Publish a message using the
publish()
function from the@salesforce/messageChannel
module. - Subscribe to a message using the
subscribe()
function from the@salesforce/messageChannel
module.
Check out the “Message Service” recipes from LWC Recipes for examples of how to use LMS.
pubsub module
The pubsub module should be used as a last resort alternative in containers that do not support the Lightning Message Service. The module provides a publish/subscribe mechanism for exchanging data across a web page. It’s a functional solution but is not officially supported or actively maintained.
Summing it up: five features for three inter-component communication patterns
That’s a wrap. In this post, we saw an overview of the three types of inter-component communication patterns, along with their respective benefits and use cases:
- Passing data down the component hierarchy with public properties, setters or methods.
- Passing data up the component hierarchy with events.
- Passing data to components that share no common ancestry with the Lightning Message Service or the pubsub module.
Here’s a recap of the different features that you can use to share data across components:
If you’d like to learn more, install and explore our LWC Recipes sample app to see these techniques at work in small code-snippets.
About the author
Philippe Ozil is a Principal Developer Advocate at Salesforce where he focuses on the Salesforce Platform. He writes technical content and speaks frequently at conferences. He is a full stack developer and enjoys working on DevOps, robotics and VR projects. Follow him on Twitter @PhilippeOzil or check his GitHub projects @pozil.