Data Stores and React in Meteor

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


If you use React, the you have probably heard of data stores as a means of separating out your data and business logic from your views (or if you haven’t looked into React, you can read our article on how to Think in React). Separating your data from your views is definitely a great step to take and helps with maintainability, decoupling, and testing.

Flux

The Flux application structure basically describes the way your data and actions should flow in your application: data can only flow down, one way in your hierarchy. Any changes to that underlying data should be dispatched as events to a central dispatcher which queues those changes and executes them. These events are executed one at a time, and each one should only be executed after the changes have been propagated through your view:

So, how do we actually implement a data store for our views to use?

Reflux

There is a great way to implement data stores into your React code thanks to Reflux, an implementation of Facebook’s Flux application structure.

In Meteor, we can easily add Reflux to our application by running: meteor add fourquet:reflux.

Once added, we can add a Data Store.

Let’s create a project where our goal is to keep track of how many times a user has clicked a button on the page. We can use a data store to store the number of times the button has been pressed, and update that number with actions that we allow the application to call.

Here are the actions that we define:

ClickActions = Reflux.createActions([
'increment',
'reset'
]);

And here is a our data store that uses those actions:

ClickStore = Reflux.createStore({
listenables: [ClickActions],
init: function () {
this._click = { total: 0 };
},
increment: function () {
this._click.total++;

this.trigger(this.getInitialState());
},
reset: function () {
this._click.total = 0;

this.trigger(this.getInitialState());
},
getInitialState: function () {
return {
total: this._click.total
}
}
});

Our data store stores the number of clicks, and provides an increment and reset action. It also provides a getInitialState method so that we can use this data store as a mixin in any of our views.

For example, the container for a component that wants to use this data store may look something like this:

ClickTextContainer = React.createClass({
mixins: [Reflux.connect(ClickStore, 'click')],
render() {
return (
<ClickText total={this.state.click.total} />
);
}
});

And we can have another component which may dispatch the increment action:

IncrementButton = React.createClass({
handleClick(e) {
e.preventDefault();
ClickStore.increment();
},
render() {
return (
<button onClick={this.handleClick}>Click Me</button>
);
}
});

We’ve now completely implemented a data store in our React application.

Next, we will create a reactive data store using a Mongo database!


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