Today I’m going to show off a little component you can make to serve as a nice state container. We’ll mix the reactivity of Meteor and the components of React to build a predictable user interface.

What are container components?

A container does data fetching and then renders its corresponding sub-component. That’s it.

The Goal

Our goal here is to wrap some presentational components with a state container to serve props and render user interfaces

Step 1 — Build the Container Component

First we need to build our Container Component

const StateContainer = class StateContainer extends React.Component {

constructor() {

super();

}

getMeteorData() {

const containerSubscription = this.props.getSubscription();

const containerCursor = this.props.containerCursor;

return {

containerSubscriptionReady: containerSubscription.ready(),

containerData: containerCursor.fetch()

}

}

render() {

let children;

// if the data is ready, iterate through the component children

// bind the containerData to the props of the children

if (this.data.containerSubscriptionReady) {

children = React.Children.map(this.props.children, (child) => {

return React.cloneElement(child, {

data: this.data.containerData

});

});

} else {

children = 'Loading...';

}

return (

<div>

<div className="with-gotham">

{children}

</div>

</div>

)

}

};



reactMixin(StateContainer.prototype, ReactMeteorData);

We’ve created a container that takes a function to return a subscription as props, as well as a cursor to fetch data when subscriptions are ready. A cool thing to point out here is while the subscription is waiting, our children render a loading screen before any content is rendered. Once the containerSubscription yields ready, we will see the contents wrapped in this container.

Step 2 — Put the container on the page

const PageComponent = class PageComponent extends React.Component {

constructor() {

super();

}



render() {

return (

<div className="flex-grid">

<div className="grid-cell">

<div className="center-container">

<h3>State Example Page</h3>

</div>

<StateContainer>

// GOING TO PUT STUFF HERE

</StateContainer>

</div>

</div>

)

}

}

Step 3 — Lets set up our props

Next we’re going to make a subscription function that returns a Meteor.subscribe call. Then we’ll build a cursor to query the data returned by the subscription.

render() {

const exampleSubscription = () => {

return Meteor.subscribe(‘stateExample’);

};



const exampleCrsr = Examples.find({_id: {$ne: Meteor.userId()}}, {

sort: {createdAt: -1},

limit: 20});

}); <StateContainer getSubscription={exampleSubscription} containerCursor={exampleCrsr}> </StateContainer>

}

Great! Now our container is locked and loaded with the necessary data to render its presentational components. Let’s bring it home.

Step 4 — Presentational Component

render() {

const exampleSubscription = () => {

return Meteor.subscribe('stateExample');

};



const exampleCrsr = Examples.find({_id: {$ne: Meteor.userId()}}, {

sort: {createdAt: -1},

limit: 20

}); <StateContainer getSubscription={exampleSubscription} containerCursor={exampleCrsr}>

<ExampleComponent/>

</StateContainer>

} // presentational component

// use a stateless component function

// Our example component inherits "data" via props by

// being wrapped in a container const ExampleComponent = ({data}) => {

const {profile} = data;

return (

<div>{profile.name}</div>

<div>{profile.birthdate}</div>

)

};

Conclusion

You’re set! You now have a small reusable state container. Feed it a subscription and a cursor, wrap it around a presentational component and you’re good to go!