How would you share state between Web Components?

Yesterday, I had an interesting chat with a friend about how I would share state between Web Components, and get them to talk to each other in a web app.
Today, let’s explore what that might look like!
An ecommerce platform An example I like to use for this kind of thing is an ecommerce platform with a few interconnected components.
You might have a <cart-link> Web Component that displays a link to the checkout page, with the number of items in the cart as it’s text.


This content originally appeared on Go Make Things and was authored by Go Make Things

Yesterday, I had an interesting chat with a friend about how I would share state between Web Components, and get them to talk to each other in a web app.

Today, let’s explore what that might look like!

An ecommerce platform

An example I like to use for this kind of thing is an ecommerce platform with a few interconnected components.

You might have a <cart-link> Web Component that displays a link to the checkout page, with the number of items in the cart as it’s text.

<cart-link>
	<a href="/checkout">🛒 2 Items</a>
</cart-link>

You might also have a <product-listing> Web Component that displays an Add to Cart button if the item isn’t in your text, or a message if it is.

<!-- Not in the cart -->
<product-listing price="39" uid="tshirt-jolly-roger">
	<button>Add to Cart - $39</button>
</product-listing>

<!-- Already in the cart -->
<product-listing price="39" uid="tshirt-jolly-roger">
	<em>This is item in your cart</em>
</product-listing>

And powering both of these Web Components is a cart variable—an object ({})—that holds the items currently in the cart.

let cart = {};

Whenever an item is added to the cart, the <cart-link> element needs to update the text about how many items are in the cart. The <product-listing> also needs to update itself to show either a <button> or message depending on whether the item is in the cart.

Let’s take a look at how to wire up all of these pieces so they can talk to each other.

A simple signal

To make this work, we’ll create a Signal class that will actually hold the cart data.

Whenever the data is updated, the Signal will emit a custom event that the other Web Components can listen to. We’ll start by storing whatever value is passed in to the this.value property.

class Signal {

	// Initialize the class
	constructor (val) {
		this.value = val;
	}

}

We’ll create a new Signal() for the cart like this…

let cart = new Signal({});

Next, we’ll add an add() method that accepts a key and val as arguments.

The method will add or update the key in the this.value object. Then, it will emit a custom cart-updated event.

Note: In a real production app, I’d either use setter and getter methods or Proxies for this. But this is a useful, simple model for teaching.

class Signal {

	// Initialize the class
	constructor (val) {
		this.value = val;
	}

	// Add a new item
	add (key, val) {

		// Update the value
		this.value[key] = val;

		// Create a new event
		let event = new CustomEvent('cart-updated', {
			bubbles: true,
			detail: {key, val}
		});

		// Dispatch the event
		return document.dispatchEvent(event);

	}

}

While we’re here, let’s also add a size() method that returns the number of items in the this.value object, and a has() method that checks if a key is in the this.value object or not.

class Signal {

	// ...

	// Get the number of items in the cart
	size () {
		return Object.keys(this.value).length;
	}

	// Check if an item is in the object
	has (key) {
		return !!this.value[key];
	}

}

For the <cart-link> component, we’ll create a render() method that gets the cart.size(), and displays it as a link inside the custom element.

customElements.define('cart-link', class extends HTMLElement {

	// Instantiate the Web Component
	constructor () {

		// Inherit parent class properties
		super();

		// Render the initial UI
		this.render();

	}

	// Render the UI
	render () {
		this.innerHTML = `<a href="/checkout">🛒 ${cart.size()} Items</a>`;
	}

});

We’ll add an event listener for the cart-updated event, and use the handleEvent() method to run the render() method whenever the cart is updated.

customElements.define('cart-link', class extends HTMLElement {

	// Instantiate the Web Component
	constructor () {

		// Inherit parent class properties
		super();

		// Render the initial UI
		this.render();

		// Listen for cart events
		document.addEventListener('cart-updated', this);

	}

	// Handle Events
	handleEvent (event) {
		this.render();
	}

	// Render the UI
	render () {
		this.innerHTML = `<a href="/checkout">🛒 ${cart.size()} Items</a>`;
	}

});

Now, whenever the cart is updated, the <cart-link> gets updated automatically.

🧐 Want to learn more about Web Components? I’m adding all of my guides around building Web Components to my members-only toolkit. Joining is a great way to support my work!

Creating the <product-listing> component

We’ll do something similar for the <product-listing> Web Component.

When the Web Component instantiates, we’ll use the Element.getAttribute() method to get the [uid] and [price] attributes, and save them to properties.

Then well run a render() method to render the UI.

customElements.define('product-listing', class extends HTMLElement {

	/**
	 * Instantiate the Web Component
	 */
	constructor () {

		// Inherit parent class properties
		super();

		// Set properties
		this.uid = this.getAttribute('uid');
		this.price = parseFloat(this.getAttribute('price'));

		// Render the initial UI
		this.render();

	}

});

Inside the render() method, we’ll use the cart.has() method to check if this.uid is in the cart already.

If it is, we’ll show a message. If not, we’ll show a button to add the item to the cart, with this.price as part of the button text.

// Render the UI
render () {
	this.innerHTML = cart.has(this.uid) ? '<em>This is item in your cart</em>' : `<button>Add to Cart - $${this.price}</button>`;
}

Next, we’ll add an event listener for the cart-updated event. We’ll also listen for click events inside the custom element.

/**
 * Instantiate the Web Component
 */
constructor () {

	// Inherit parent class properties
	super();

	// Set properties
	this.uid = this.getAttribute('uid');
	this.price = parseFloat(this.getAttribute('price'));

	// Render the initial UI
	this.render();

	// Listen for events
	document.addEventListener('cart-updated', this);
	this.addEventListener('click', this);

}

Inside the handleEvent() method, we’ll check if the event.type is cart-updated.

If so, we’ll run the render() method to update the UI, and return to end the function. If the event.type is click, and the event.target (the clicked element) is or is inside a button, we’ll run the cart.add() method to add this.uid to the cart object.

// Handle events
handleEvent (event) {

	// If it's a cart update event
	if (event.type === 'cart-updated') {
		this.render();
		return;
	}

	// If it's a click on the button
	if (event.type === 'click' && event.target.closest('button')) {
		cart.add(this.uid, this.price);
	}

}

Adding the item will trigger the cart-updated event, which will trigger a render of the UI.

Putting it all together

Here’s a demo you can use to play around with this idea. And if you’d prefer, here’s the downloadable source code on GitHub.

Depending on the use case, there are other ways you might handle this kind of thing. But this would probably be my starting point for an app like this.

Like this? A Lean Web Club membership is the best way to support my work and help me create more free content.


This content originally appeared on Go Make Things and was authored by Go Make Things


Print Share Comment Cite Upload Translate Updates
APA

Go Make Things | Sciencx (2025-01-21T14:30:00+00:00) How would you share state between Web Components?. Retrieved from https://www.scien.cx/2025/01/21/how-would-you-share-state-between-web-components/

MLA
" » How would you share state between Web Components?." Go Make Things | Sciencx - Tuesday January 21, 2025, https://www.scien.cx/2025/01/21/how-would-you-share-state-between-web-components/
HARVARD
Go Make Things | Sciencx Tuesday January 21, 2025 » How would you share state between Web Components?., viewed ,<https://www.scien.cx/2025/01/21/how-would-you-share-state-between-web-components/>
VANCOUVER
Go Make Things | Sciencx - » How would you share state between Web Components?. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2025/01/21/how-would-you-share-state-between-web-components/
CHICAGO
" » How would you share state between Web Components?." Go Make Things | Sciencx - Accessed . https://www.scien.cx/2025/01/21/how-would-you-share-state-between-web-components/
IEEE
" » How would you share state between Web Components?." Go Make Things | Sciencx [Online]. Available: https://www.scien.cx/2025/01/21/how-would-you-share-state-between-web-components/. [Accessed: ]
rf:citation
» How would you share state between Web Components? | Go Make Things | Sciencx | https://www.scien.cx/2025/01/21/how-would-you-share-state-between-web-components/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.