Mixins - JavaScript | LWC. A short introduction
One of the most used quotes regarding mixins is from Mixin-based Inheritance Gilad Bracha and William Cook.
A mixin is an abstract subclass; i.e. a subclass definition that may be applied to different superclasses to create a related family of modified classes.
We only need to think about the quote in the context of class extensibility in JavaScript. That a class can only be extended by one, another class. And we might be able to figure out what mixins are meant to achieve.
Basically, mixins allow us to do a kind of multiple inheritance. By using mixins, we can extend a class with an unlimited number of other classes because each mixin can extend another mixin. While preserving powerful JavaScript language features such as:
What about first-class functions? It's a feature of languages that classes and functions are treated like any other variable. A class can be passed to the function as an argument. Or it can be assigned to a declared variable. Is such a feature of the language useful? Of course it is and is essential in building mixins in JavaScript!
Now we know what mixins are and what they are for. Let's go through a practical example.
Let’s assume that we have built a simple LWC component. Wizard to add a new college application. Let's call it a Study Application Component.
After some time, someone assigned us a ticket saying that we need to add toast-related functionality to our component. We don't want to change our perfect code by adding functionality that is not strictly related to our component. Let's extend our component with the Toast features mixin. New functions will be in a different class and what's more important will be reusable.
But before that let’s see on the current inheritance of our LWC component. Our component is already extended by the LightningElement class.
It's a good time to use mixins because we need to extend our class with two other classes. Let's create a Toast mixin and include it in our component declaration.
Recommended by LinkedIn
import { ShowToastEvent } from "lightning/platformShowToastEvent"
let ToastService = (superclass) => class extends superclass {
showToast(variant, message, title, mode = "dismissible") {
dispatchEvent(new ShowToastEvent({
variant,
message,
title,
mode
}));
}
showSuccessToast(message, title = "Success") {
this.showToast("success", message, title);
}
}
export { ToastService };
We didn't add any new logic to our component. We just added new responsibilities and now, our component has the ability to display our success toast!
What about the syntax? We need to know which parts of the class will be inherited by the other class. Let's consider the syntax we have to use in the LWC and take another look at the last example.
In this case, the LightningElement class is extended with the TosatService class. This creates the application mixin. Next, the StudyApplicationComponent class is extended with the mentioned application mixin. So the superclass of the LightningElement is ToastService. The superclass of the StudyApplicationComponent is the application mixin.
Do you think the current syntax is confusing? I have a good message for you! You can make use of the first-class JavaScript language attribute to change the syntax to whatever you want. Below you can find two examples of how you can do it.
class MixinLoader {
constructor(superclass) {
this.superclass = superclass;
}
with(...mixins) {
return mixins.reduce((accumulator, mixin) => mixin(accumulator), this.superclass);
}
}
let mix = (superclass) => new MixinLoader(superclass);
export { mix };
And the second one, in the builder style!
class MixinsBuilder {
constructor(superclass) {
this.superclass = superclass;
}
loadToastMixin() {
this.superclass = ToastMixin(this.superclass);
return this;
}
…
build() {
return this.superclass;
}
}
let base = (superclass) => new MixinsBuilder(superclass);
export { base };
Salesforce Technical Leader | CRM Manager | Salesforce Trailblazer Community Group Leader
1yNice! Waiting for more content 😉
🔧 ForVendi: Customizable Salesforce Solutions for Every Client Need
1yDaniel Legawiec really nice article, thanks for sharing!