Building real-time React Applications with Redux and Meteor

Philipp Sporrer
Backlog stories
Published in
5 min readAug 7, 2016

--

At Backlog we recently ran into some issues with our Meteor app.

  • Using Webpack with Meteor slowed down our server build process and our tests
  • Using Tracker caused some unexpected performance issues, that always required digging deep to understand what is going on
  • Keeping an overview over client side state changes got really hard

This article explains how we plan to get rid of all these problems at once, by using Meteor only in the backend. But even if you are not using Meteor, this article shows an interesting approach to making your React application real-time.

Let's get going

As a starting point, I will use the Todos App from Dan Abramov’s egghead.io course “Building React Applications with Idiomatic Redux” (source).

The app lets you add todos to a list, toggle them as done, and filter for all, active and completed todos. This is what it looks like:

For many of my projects, I have been using Meteor. Meteor is a great tool. It is very easy to pick up and is real-time by default. But there is one thing that always annoyed me: There is too much magic happening out of my control that I don’t fully understand. This leads to unexpected behaviour and often bad UX.

The best part about building the frontend with Redux compared to Meteor is, that it is predictable and comprehensible. There is no magic. I can understand what happens, when it happens and why it happens.

Where Meteor really shines though is its data layer. It is really easy to set up a server without much configuration that is real-time by default.

Coming back to the React/Redux Todos App: It is missing something! You probably guessed it:

A server

As I mentioned Meteor makes it really easy to setup a simple server that delivers data in real-time to your clients. This is what we get after setting up a simple server and connecting it to the browser using Asteroid (a simple DDP client)

Asteroid is a wrapper library for ddp.js, which follows the DDP spec. So all the heavy lifting is done by existing libraries 😅. Asteroid lets you subscribe to all incoming DDP messages of the types “added”, “changed” and “removed”. Every time one of these messages arrives our registered callback function gets called and we can dispatch a Redux action that represents the DDP message. That way we guarantee that we only have one store and that the only way our data gets into the store is via actions. No magic. Let’s take a look at the code for this:

I figured it is probably easiest to immediately set up the DDP listeners after creating the store. In order for the listeners to dispatch Redux actions, we need to pass them the store.dispatch method. Now every time a todo gets added, changed or removed we dispatch an action and handle it in our reducers, which is nothing special and we only need to make a few changes to make the reducers handle the “new” action format.

While this is nice and works really well, we lost something that you also get for free when using Meteor on the client:

Optimistic UI

As you can see in the screen recording above, it takes a moment before the todo is added. Why? Because we need to wait until the request for adding the Todo has returned from the server. We can fix this by doing so-called optimistic updates. Normally, you get this for free when using Meteor on the client. Since we cannot call Meteor methods on the client anymore, we need to do optimistic updates ourselves (like the rest of the world 😜). This is how it works when adding a todo:

First of all, we optimistically dispatch a “DDP_ADDED” action for the new todo, assuming that the server will accept it. Then we call the Meteor method “addTodo” (calling a meteor method is similar to calling a REST endpoint) with the new todo. When the request succeeds, we don’t need to do anything, since we already added the todo optimistically. When the request fails, however, we simply emit a “DDP_REMOVED” action, which will remove the new todo from our client.

Adding a todo is now much faster than before (who would have thought 😬)

And this is what it looks like when the server throws an error when we try to add the todo:

While having a todo item appear and then disappear after a second is very bad UX, we should never let this happen in the first place. We should do all necessary validations on the client before doing the optimistic update, so we can be “sure” that the server will allow the operation.

However, this implementation of optimistic UI has a few drawbacks. One of these drawbacks is that the ID is solely generated by the client and passed on to the server, assuming that it will use this ID for the new todo. This means the server has to trust the client, which it almost never should. You can read how Meteor solves this problem here.

As a follow up article, we will try to fix this problem by passing the server a random generator seed as described in the Meteor guide. If you are interested follow this publication to get notified once the article is published.

There might be more drawbacks to this “naive” implementation of optimistic UI. If you find one, please share it in the comments.

Conclusion

You can find the code for the example App here. It shows how you can easily make your React-Redux app real-time by integrating it with a Meteor server with just a couple of lines of code and without losing Optimistic UI. If you want to read more about this setup, there is another great article by Julian Cwirco about this setup, which inspired me to write this one.

While it is really easy to set up a React app with a Meteor backend you miss out on all the client-side features of Meteor. There is a lot more work that you need to do yourself. But in my opinion, it is worth the effort.

What do you think? I would love to hear your opinion about this setup in the comments 😁

--

--