The beautiful of simplicity of React.js doesn’t only extend to components, but also mixins. Essentially mixins can extend components and all of the default lifecycle methods.
Through the use of mixins we can take repetitive tasks and break them out into their own standalone pieces of functionality that can be optionally included within one or more components.
In this post we are only going to be building a really simple React.js mixin. The purpose of this post is to get you familiar with how mixins are created so you can go on and explore them further.
The mixin we are going to be building is actually something I recently created for a personal project to conditionally include stylesheets. However, I have stripped away load wait events and other things to make it more simple for the purposes of this post (this code will insert a stylesheet but won’t tell you if there is an error or if it has loaded).
As you will notice, defining a React.js mixin can be as simple as defining a new Object
and writing your code like you would any normal component. Because mixins are included within an existing component, we don’t need to worry about the context: React will handle this for us. We are effectively subclassing our component(s).
// stylesheet-mixin.js
var Stylesheet = {
loadStylesheet: function(url) {
var head = document.getElementsByTagName('head')[0];
var link = document.createElement('link');
link.setAttribute('rel', 'stylesheet');
link.setAttribute('href', url);
link.setAttribute('type', 'text/css');
}
};
We have a simple enough mixin that will insert a stylesheet into the DOM for us. Now we create a simple made-up component and include our mixin.
var LoginComponent = React.createClass({
mixins: [Stylesheet],
componentDidMount() {
this.loadStylesheet('/css/login.css');
},
render: function() {
return <div>This is a styled span element</div>;
}
});
React.renderComponent(<LoginComponent />, document.body);
For the sake of our example, if we were to create a file called login.css
within our CSS folder and create a class called .mySpanStyle we would see our span become stylised with whatever we put on it.
As you can see we have created our component and called it “Stylesheet” – to use it we include our mixin and then include it in the mixins array (as shown in our LoginComponent). That’s all it takes to include a mixin, it is easy (like React itself).
What can we do within a mixin?
Pretty much anything. Mixins allow us to subclass functionality within a component and as discussed earlier we can even define our own React lifecycle events so we can do things when a component is mounted, props change or any other lifecycle event that React ships with.
Keep in mind that declaring a lifecycle method in a mixin does not override it on the component itself. If you declare componentDidMount
within your mixin and your component defines the same lifecycle method: both will be called. Keep in mind that mixin lifecycle methods will always be called first, followed by component lifecycle methods.
Yo dawg…
I heard you like mixins. So you can put mixins in your mixins, so you can mix while you mixin. In React mixins can actually include other mixins, so whether you are including your own mixins or including one of the bundled mixins that comes with React, you can. There is no limit to the depth, you can endlessly include mixins from within your mixins.
You can also include more than one mixin within a component or mixin at once, evident by the fact that the mixins property expects an array to be provided.
Gotchas
You cannot declare render
within your mixins, attempting to do so will throw an error. Defining render more than once makes no sense anyway, so you should hopefully never encounter this error.
You need to be careful when setting state values from within a mixin as well. If a component and mixin are changing the same state value, one will override the other. As a rule of thumb you should never modify the same state value as a component would. Consider namespacing state values if you need to access them from a component or vice-versa.
While lifecycle methods can be defined within your mixins, you cannot declare an already delcared method from a component. If you create a method on the login component called login
and then you attempt to redeclare it within your mixin, an invariant violation will be thrown as React doesn’t allow you to override and duplicate user created component methods.
Conclusion
The benefits of creating React.js mixins is that they keep our components clean and they promote reuse as they are essentially components themselves. The above approach I have taken allows me to only include stylesheets on a component-by-component basis, but you could easily use them for other things too.
Thanks for the post.
I only have on questions… how does the [Stylesheet] shows up in that second part of the code.
How are you supose to link 2 completely diferent files? do you do require(‘stylesheet-mixin.js’) ?
thanks
A minor nitpick: you actually *can* declare the render method in a mixin; the real rule is that, between the class itself and all its mixins, there can only be one render method (grep for DEFINE_ONCE in the react codebase).
That is, if you want to have the mixin take complete responsibility for rendering, you can; you just can’t have both a render method in the main component *and* one in the mixin, since then it’s ill-defined which one to use.