Whilst frequenting my favourite slack haunt one of my fellow slackers mentioned that they had recently been googling up a storm and looking at a number of different React examples. Whilst researching they had noticed that in some examples components were implemented using a class yet others were using a function.

So, the intrepid slacker went about seeking the answer to the question “What’s the deal with the function-y lookin’ components and the class-y ones?!”  I thought this was a great question and perhaps not all that obvious at first glance so in this post I’d like to walk you through what exactly that difference is.

 

Defining the problem

Like most repeated patterns that you’ve seen this pattern has come into existence to solve a problem. So let’s begin by defining that problem. Throughout this article I’m going to be using example code to illustrate my points. After a cursory glance of the code you should be able to recognise that what the example does when it’s built.

I’ve made myself a React robot buddy who loves nothing more than to Hi 5 with his best and only buddy in the whole world, me!  Let’s take a look at the code for my little guy below:

import React, { Component } from 'react';
class HiFive extends Component {
constructor(props) {
super(props);
this.state = {
isHiFived: false,
};
this.doHiFive = this.doHiFive.bind(this);
}
doHiFive() {
this.setState({
isHiFived: true,
});
setTimeout(() => {
this.setState({
isHiFived: false,
});
}, 2000);
}
render() {
const { isHiFived } = this.state;
return (
<div>
<div>{isHiFived ? 'YEAAAAH WOOOOOH!!!' : 'Hey buddy! Hi 5?!' }</div>
<button onClick={this.doHiFive} disabled={isHiFived}>Give Hi5</button>
</div>
);
}
}
export default HiFive;

If you were to put this into your build pipeline and transpile it out you’d find that it works perfect fine. So you might be asking yourself “Where’s the problem?”. Well, separation of concerns is our main issue here.  You can clearly see that within this one component we have housed state and the management of that state right along side the logic used to render a visual representation of that state.

This seems manageable in this small and safe example environment but you will find that this cross cutting of concerns presents more and more of a problem the larger your applications and their components grow. Even within the context of the simple problem presented, things can get complicated quickly without proper management.

What if I decided I wanted my robot buddy to do more? Let’s say I added a button so he could give me a hug and another button to beat up mean bullies for me (I haven’t thought about this too much). If I were to implement this new functionality to operate on and store state then then I would also need to modify the UI to display these pieces of state. You can imagine that this would already make for a very cluttered and potentially difficult to maintain component.

 

Solving the problem

The answer to this problem is to separate concerns. We need to get to a point where we have one component that takes care of state and it’s manipulation and other component that concerns itself only with displaying that state to the user.

You can then make the “stateful” component take the display component as a child and pass it’s state into the display component. And there you have it, you’ve just learned the pattern that you will most often seen referred to as Container components and Presentation components. The main idea that we have a smart “stateful” container component that houses one or more dumb “stateless” presentation component.

Let’s first take a look at what our container component would look like:

import React, { Component } from 'react';
import HiFive from './HiFive';
class HiFiveContainer extends Component {
constructor(props) {
super(props);
this.state = {
isHiFived: false,
};
this.doHiFive = this.doHiFive.bind(this);
}
doHiFive() {
this.setState({
isHiFived: true,
});
setTimeout(() => {
this.setState({
isHiFived: false,
});
}, 2000);
}
render() {
return (
<HiFive
isHiFived={this.state.isHiFived}
doHiFive={this.doHiFive}
/>
);
}
}
export default HiFiveContainer;

I’ve highlighted the very few lines that have actually needed to change. All we have done here is change what the component actually renders. This might not seem like a big change but the implication of what we’ve done with regards to the maintainability of our code is big.

We now have a component which has state and knows how to manipulate it but doesn’t care at all how this state is rendered on the screen. It ships that responsibility off to the HiFive presentation component.

This means that if we want to change the way things get rendered then we need to change the presentation component and we know that in making this change the logic behind how the data is stored and manipulated will remain intact and untouched. Equally if I wanted to make my robot recover from a high five quicker I can change this functionality in my container component and, provided I haven’t changed which props get passed, my presentation component doesn’t need any refactoring at all.

The point here is each component has one reason to change and we can all agree on the fact that we like this.

So what does our presentational component look like now?

import React, { Component, PropTypes } from 'react';
class HiFive extends Component {
render() {
const { isHiFived, doHiFive } = this.props;
return (
<div>
<div>{isHiFived ? 'YEAAAAH WOOOOOH!!!' : 'Hey buddy! Hi 5?!' }</div>
<button onClick={doHiFive} disabled={isHiFived}>Give Hi5</button>
</div>
);
}
}
HiFive.propTypes = {
isHiFived: PropTypes.bool.isRequired,
doHiFive: PropTypes.func.isRequired,
};
export default HiFive;

This time I’ve highlighted the lines that haven’t changed. Nothing has really changed here with regards to how this part of the component actually works. Except now, rather than displaying the data directly from state, our presentation component is destructuring the variables and event handlers that it have been passed via props and using them instead.

After seeing the implementation of the presentation component I’m sure you’ve seen another benefit. Our presentation component is pretty darned reusable at this point, wouldn’t you agree? As long as it gets passed the correct props as prescribed by it’s prop types declaration then it’s good to display whatever it’s given.

So I could easily put together an army of robots that all give slightly different Hi 5’s! Even away from this contrived (and arguably silly) example I’m sure you can see how this adds reusability to both the container and presentation component. That’s a lot of “ilities” we’ve collected now from this pattern, that’s a good sign!

 

Making the solution your b Solving the problem really well

Now that we have discovered container components and presentation components you may think it’s time to skip off into the sun set with a basket of “ilities” under your arm. You could happily do this but what if I could give you some sweet shades to wear as you skipped off wouldn’t that be cool? Of course it would! If there’s anything worth doing in this world, it’s worth looking cool whilst you’re doing it.

So for extra style points what you could do is refactor your your presentation component into what is known as a “Stateless Functional Component”. The internet loves a good acronym so you may have heard of them referred to as SFCs. SFCs were introduced to React in version 0.14 and their aim is to cut away as much of noise in the code of very simple components and leave as much of the signal intact as we possibly can.

Given that presentation components rarely do more than simply display data, it goes without saying that they are most often candidates to become SFCs. Let’s take a look at why the presentation component for my robot would look like as an SFC.

import React, { PropTypes } from 'react';
const HiFive = (props) => (
<div>
<div>{props.isHiFived ? 'YEAAAAH WOOOOOH!!!' : 'Hey buddy! Hi 5?!' }</div>
<button onClick={props.doHiFive} disabled={props.isHiFived}>Give Hi5</button>
</div>
);
HiFive.propTypes = {
isHiFived: PropTypes.bool.isRequired,
doHiFive: PropTypes.bool.isRequired,
};
export default HiFive;

Stylin’ huh? I really like the way that SFCs help to draw your attention to what’s important in the component. Take a moment to compare this new SFC version of the presentation component with what we had previously. See how when you compare them that the screen seems to be almost dominated by code that is ultimately unrelated to rendering. Now take a look at the SFC and you’ll be able to quickly recognise that in this version the rendering code holds a far more prominent position and your eyes are drawn straight to the JSX which is, after all, the main part of this component.

 

The bottom line

The container and presentation component pattern is fairly well established in the React community now and you should now be able to see why. This pattern really does go a long way to helping you to craft reusable and well defined components.

Also, with the addition of SFCs you now have a great way to write succinct and good looking code to make you feel like an uber coder and help you write code that will delight both yourself and your colleagues. I look forward to seeing you in my next post. Till next time!