Using Meteor Data and React with Meteor 1.3 beta

Arunoda Susiripala
KADIRA VOICE
Published in
5 min readJan 30, 2016

--

In a previous post, I talked about how to use React with Meteor 1.3. In that post, I showed how to get React from NPM and use FlowRouter to build a simple app.

This is a sequel to that, where I show how to use Meteor’s data system with React. In technical terms, we are trying to get data with a subscription and render a component based on that data.

React Container Pattern

Before we jump into that, we need to learn the idea behind “React Container Pattern”. It will allow you to separate the data layer and the presentation layer (UI) very easily.

Have a look at the following screenshot:

Here we have a component(BlogPost) that contains the UI. Then we use something called a “container component” which fetches the data. Then it’ll pass that data into the UI component via props.

To learn more about this pattern, have a look at the following article:

Now we have enough knowledge about Containers. We can continue.

Publication

Here we are trying to get a list of MongoDB documents from a collection called Posts. Here’s the publication we’ll be using:

UI Component

Then we need to have a UI component to render those posts. Here it is:

Here we are using a functional stateless component. It will get data via props and render our UI.

We are also using some ES2015 code. If that’s something new to you, follow this short course: Say Hello to ES2015

The Container

Now we need to create a container that fetches data. For that, we are using react-komposer via NPM. It’s a universal React container composing library.

As you’ve just seen, we write our subscription and data fetching logic as a composer function.

This composer function runs inside a Tracker. So, you can use any reactive code within this composer function.

Once you have the data, you can call the onData function like this:

const posts = Posts.find({}, {sort: {_id: 1}}).fetch();
onData(null, {posts});

First argument of the composer functions contains props passed to the container. You can use them to load your data.

Then, we compose the container like this.

export default composeWithTracker(composer)(PostList);

At the end you’ll get a React component.

Rendering the Container

Now it’s time to render our container.

Make sure that you render the container, not the UI component.

We can do it like this:

Once it’s rendered, here’s how we can see it in the React Dev tools.

As you can see, our UI component is wrapped by the container. The container passes data to the UI component via props.

A Complete App

You can compose containers like this and build your whole app. Here’s a simple app you can refer to: https://github.com/kadira-samples/meteor-data-and-react

Say Hello to Mantra

We created Mantra, extending these ideas further for building maintainable, future-proof Meteor apps.

It’s an application architecture for Meteor.

Give it a try. You’ll love it.

FAQ

How do I unsubscribe my subscriptions?

composeWithTracker runs inside a tracker and it’ll stop the tracker when the container is unmounting. Tracker knows how to unsubscribe subscriptions properly.

So, you don’t need to worry about it.

How do I show a loading screen?

react-komposer has a built-in loading functionality. It handles that for you. But you can override the default loading component as shown below:

const MyLoading = () => (<div>Hmm…</div>);
const Container = compose(composerFunction, MyLoading)(Component);

How does container know that the container is loading data?

When the container is starting, there is no data. So, it shows the loading screen.

Then, once you put data into the container, it’ll stop the loading screen and render the UI component.

If you need to get the loading screen again, you need to send `null` as data:

function composer(props, onData) {
...
onData(null, null);
};

Can I show the loading indicator in the UI component itself?

You can handle the loading screen inside your component as well. To do that, always send some data to the container, then pass a loading indicator to the UI component via data. Here’s an example:

I don’t need a loading screen at all. How do I do that?

This is also similar to the above question. Make sure you are always sending something to the container.

Can I access props passed to the container from the UI component?

Yes, of course. Check this:

How do I use React lifecycle hooks?

For that, you don’t need to work with the container. Just add lifecycle hooks to your UI component. See the following example:

How do I set a custom display name?

By default, container’s displayName is something like this:

Container(UIComponentName)

Container itself is a react component. So, you can simply set a displayName to override the default displayName.

const Container = composeWithTracker(composer)(PostList);
Container.displayName = ‘MyContainer’;

How do I handle errors?

You can pass an error to the container as the first argument of onData callback. Then it’ll display the error on the UI. But you can easily override it and render a custom error component as shown below.

const MyError = ({error}) => (<div>Error: {error.message}</div>);
const Container = compose(onPropsChange, null, MyError)(UIComp);

Make sure to pass a JavaScript Error object as the error.

Can I create a container to a container?

Container is also a React component. You can create a container to a container. We have a utility function called composeAll which helps you to do it.

Is this the right way to use React?

There is no right or wrong way. But, this is how we load data into a component in modern React. This pattern is used by popular data management libraries such as Relay and Redux (via react-redux).

Is this recommended by MDG?

Seems like it’ll be.

Follow KADIRA VOICE for articles like this.

--

--