The React Container — Separating Concerns

This article was originally published on January 14, 2016 on The Capsule Cat Blog. For archive purposes, we moved it here!


A React container is a pattern where you split data fetching from the actual React component that will render that data. It was introduced in the React.js Conf 2015, which you can view here:

But the main thing to take away is this quote from the presentation:

A container actually does data fetching, and then it renders its corresponding subcomponent — that’s it.
— — Jason Bonta, Facebook

For example, if we have a BudgetWidget, we need a BudgetWidgetContainer.

If we have a TodoWidget, we need a TodoWidgetContainer.

Containers should not have props passed down to them, that way they can be fluid and moved around. Containers also allow you to unit test your inner widget, as well as change data sources whenever you want.

Real Example

We’ll be using Meteor as our example. Let’s first make a very simple React component:

MyName = React.createClass({
mixins: [PureRenderMixin],
render() {
return (
<div>{this.props.name}</div>
);
}
});

This component will display the name given to it by props. Pretty simple. It’s also really easy to test: when we pass in name="Sally", we should see <div>Sally</div> as the rendered output.

But what if name is supposed to come from some reactive data source? Maybe the name is constantly changing and we want to display updates immediately. We can use a container to bind to that reactive source, and then have that container render the MyName component:

MyNameContainer = React.createClass({
mixins: [MeteorDataMixin],
getMeteorData() {
var subscription = Meteor.subscribe('names');
return {
ready: subscription.ready()
name: Names.findOne({ _id: 1}).fetch().name
};
},
render() {
if (! this.data.ready) {
return <Loading />
}
return (
<MyName name={this.data.name} />
);
}
});

Why All This Work?

By creating React container components, we did the following:

  1. We moved our subscription up a level into the container.
  2. We moved the logic for rendering the loading template up a level.

And we got the following benefits:

  1. We separated our data-fetching and rendering concerns.
  2. Our MyName component can now be used in a static context. I.e. there is no dependency in the component itself on where the data comes from. We can render static strings with it as well.
  3. We can use the PureRenderMixin in the MyName component for a small performance boost.

Thanks for reading! If you liked this article, feel free to follow us on Twitter.

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.