React for Meteor Developers

Nick Wientge

What is React?

React is a JavaScript library built by a group of engineers at Facebook and Instagram. It describes itself as a "JavaScript library for building user interfaces". Whereas other JavaScript libraries like Angular and Ember contain features related to data fetching, data modeling, controllers, etc - React is only concerned with the "view" of your application.

Does React Replace Meteor?

Nope! Since React is only a "user interface library" it only replaces the "views" of your Meteor apps - that part that Meteor calls Blaze. So rather than writing your interface using Blaze templates, helpers and events handlers, you write them using React components. You can still leverage all of the great time-saving, productivity-boosting features of Meteor like automatic file loading, a simple unified package manager, realtime updates out-of-the-box, etc, etc.

Advantages over Blaze

So if Meteor already has Blaze, why would you want to use React?

Battle Tested

React was developed out of the real-world experiences of the engineers at two of the world's largest consumer web applications: Facebook and Instagram. If it works for those guys there's a good chance it will work for your team too!

Predictable

Anyone who has used Meteor for any amount of time has probably found themselves struggling to wrangle multiple "reactive" data sources. Meteor's realtime nature can be both a blessing and a curse. React attempts to ease this complexity by intelligently "refreshing" your entire component everytime its data changes. For those of us coming from a server side background, this can feel like the "good old days" of developing simple request/response interactions.

Focused

React encourages you to write small, reusable components with a single focus. For larger projects this can be a godsend compared to the monolothic Blaze templates and "jQuery soup" that you often see in big Meteor apps.

Scalable

React is about more than just writing code that works, it's also about writing code that works for your team. React allows you to write code that your teamates can comprehend quickly and modify confidently.

Opinionated

While watching a React talk titled "React: RESTful UI Rendering" (which I highly reccommend, especially if you are coming from a Rails background as I am) I was introduced to the term The Pit of Success.

The Pit of Success: in stark contrast to a summit, a peak, or a journey across a desert to find victory through many trials and surprises, we want our customers to simply fall into winning practices by using our platform and frameworks. To the extent that we make it easy to get into trouble we fail.

-- Rico Mariani, MS Research MindSwap Oct 2003.

React can be very frustrating at first because it literally forces you to do things the "right" way. However, anytime I hit a wall with React I later realized it was because I was trying to do something that would have gotten me in trouble later. If you find yourself initially getting frustrated with React I encourage you to stick with it a while longer and try to embrace "The React Way" of doing things.

React Lessons Learned

The official React docs do a great job explaining the key concepts of React and are a great place to start if you're looking to learn the basics. In this section I'll focus on two key best practices we've learned while building our first React app.

1. Keep your children dumb

The key to keeping your React components small and focused is to nest them in a parent/child hierarchy. React calls this composability. I've found that there are two primary concepts you need to know to do this the "React Way":

Parents talk down to children, because children are dumb

You can probably tell I'm not a parent ;) - but the key take away here is that parent components are responsible for any computations or data fetching and then passing the raw data to child components. Child components should be as simple (or "dumb") as possible, just dutifully rendering the data that they are passed.

Parents tell children what to do, not the other way around

Children components often need to trigger events or modify state. Think of a <DeleteButton /> component nested inside of a <PostItem /> component which is nested in a <PostList />. In this case it's the <PostList />'s responsibility to tell the <DeleteButton /> what to do when clicked. This is done by passing callbacks all the way down the hierarchy:

2. Keep your JSX clean

As controversial as JSX is, there's a lot of power in being able to build your interface using JavaScript rather than an abstract templating language. However I don't think that means it's OK to put a lot of logic in your JSX markup. If you look at the code example below, on the left you will see a common render function. The example on the right contains more lines of code, but the JSX portion of the component is much cleaner and easier to read.

Using React with Meteor

Ok, so you're ready to give this React thing a try? Lucky for you Meteor makes this super easy. In fact, they've made it so easy that they've already written a great tutorial for it so that I dont have to! Instead I'll focus on a few of the key lessons we've learned while integrating React and Meteor:

getMeteorData

Any Meteor data sources you want to access in your components should happen in getMeteorData - not getInitialState or componentWillMount. This includes the obvious things like data from your collections - but also the subscriptions to those collections as well as all other reactive data sources like Session, Meteor.user, ReactiveVar, etc.

Container Components

Speaking of fetching data, there's a common React pattern called "Container Components" that we've found particularly useful. The general idea is to separate your data-fetching and rendering concerns by wrapping your components in "containers" whose sole responsibility is to fetch the data needed by its children. This fits right in with React's concept of composability mentioned above. There's a great overview of Container Components on Medium if you'd like to dig in deeper.

Embrace the Ecosystem

One of the 7 Principles of Meteor is "Embrace the Ecosystem". When building UIs with React I've found that leveraging existing React components is hugely helpful. React Router, React Bootstrap and Material UI are just a few of the packages we've leveraged from the React community to boost our productivity.

What the Flux?

If you've read anything about React, you've probably come across something called Flux. So what is Flux?

The Glue Between Components

If you remember above I mentioned that React components only communicate hierarchically--between parents and their children. So what if you want two sibling components to communicate? Or several components that are all in totally different areas of your app? This is where Flux comes in. You can think of Flux as a repository of shared application state (which Flux calls "Stores") and a global event bus (which Flux calls the "Dispatcher"). Components that want to share state would subscribe to a Store (or mutliple Stores), and send events to the Dispatcher (the global event bus) to modify the state in the Store(s). When a Store is modified, all of its listener components re-render appropriately.

Flux + Meteor

So does Meteor need Flux? Meteor's collections and server-side methods can replace a lot of what you would use Flux for. If your components "subscribe" to a Meteor collection in getMeteorData they will re-render appropriately whenever that collection is modififed. In my experience I haven't felt the need to implement a Flux library. However there has been quite a bit of discussion about Meteor and Flux on the official Meteor forums, as well as some great examples on Github, so I urge you to check those out and form your own opinion.

React Native

Another React buzz word you may have heard is React Native. Introduced by Tom Occhino at this year's React Conf, React Native took the web development community by storm promising the ability to write truly native mobile apps using JavaScript.

But Meteor Already Supports Cordova!

In his keynote Tom made the bold statement that "Write Once, Run Everywhere" is a "pipe dream" and that the goal instead should be to "Learn Once, Write Anywhere". This directly contradicts Meteor's motivation for including Cordova support. So who's right? Well as always, it depends. It's hard to beat the look and feel of a truly native app and React Native takes a lot of the pain out of building them, so if you have the resources it's a great option. But for teams on a tight budget or timeline, or whose audience may be less sensitive to the differences between native and hybrid apps, Cordova is still a valid option.

React Native + Meteor

At Differential we're currently right smack in the middle of our first React Native + Meteor project, so look for a future blog post from our own Spencer Carli detailing the highs and lows of integrating React Native and Meteor. And feel free to nag him on Twitter in the meantime ;)

Conclusion

Should you use React in your next Meteor project?

If you're just getting started with Meteor - and especially if you're just getting started with JavaScript development - the simplicity and ease-of-use of Meteor's Blaze is hard to beat. For smaller apps, MVPs, and hackathons, you'd be hard-pressed to find a more efficient way of building modern, reactive, clint-side web apps.

But as your application - and more importantly your team - grows, you may find yourself feeling the pain of unpredictable application state, duplicated code and "jQuery Soup". In that case I've found that React is a great choice for building predictable, scalable apps and feels right at home in a Meteor app.