« Scott Nonnenberg


R for React (NERP stack part 3)

2016 Feb 15

Welcome to Part 3 of my series (Part 1, Part 2) about a new, more-fun-than-MEAN, more-illuminating-than-LAMP development stack. Today we take a look at the Pros and Cons of React.

Remember, NERP is:

Today we finally move beyond the letters we share with MEAN. The first of these is React. It’s pretty hot right now, but we’ll be sure to cut through the hype.

Apples? Oranges?

First, some terminology. React is frequently used in the same breath as Angular, Ember, Knockout, Backbone, and other MVC web frameworks. But the truth is that React can’t be compared directly with these frameworks, as it says on the React homepage:

“Lots of people use React as the V in MVC. Since React makes no assumptions about the rest of your technology stack, it’s easy to try it out on a small feature in an existing project.” (https://facebook.github.io/react/)

So React isn’t a complete solution by itself. You give it data and it renders or re-renders HTML. And will emit events on user interaction. But that’s it. So, when I talk about React, I assume that you’ve selected a Flux implementation to go along with it.

Flux

You may have heard this nebulous term in connection with React. In a phrase, it is the data flow for your application. When the user makes a change in a textbox, where does that new data go? How does overall application state change? What exactly is the overall application state?

The old model (jQuery and most frameworks), is to make some local UI change to the DOM then emit an event. Other components listening for that event can make their local DOM changes, then emit yet more events, and so on. In a large app, it gets hard to track the cascade of changes both to DOM and application state. Especially since they can easily get out of sync!

Flux dictates that the user’s change must first affect the central application state, before attempting to do anything with that change locally. When application state changes, the app re-renders, finally changing the DOM. Cascading data changes are explicitly disallowed, greatly simplifying already-complex large applications.

This means that all application state is entirely separate from the DOM. On save of user settings, for example, we don’t extract data from the form on the page - we use the current application state. Want to know what the UI should look like? Just look at the current application state.

Redux

Redux is one of the primary players in the world of Flux implementations. In contrast to the majority, it has just one central object (the store) as its application state.

I has a very constrained data flow. Small objects (actions) are passed through a central chain of middleware functions (not the same as Express middleware) which can modify those actions, then the actions are passed through a set of reducer functions which are the only thing which can change the central store. Finally, when the store changes, your React view components are re-rendered with its new data.

It’s the simplicity, and ultimately the restrictions, inherent to this architecture which make it worth using. Extremely useful functionality can be built on top of it:

R for React

So now we know a little bit more about what React provides, and what people generally mean when they talk about it. Should we use it?

The Pros

If some of the stuff above already seemed pretty great to you, there’s more!

  1. Just re-render!
  2. Build-time errors with JSX
  3. Flexible rendering
  4. Lightweight
  5. You will conform!

1. Just re-render!

The techniques of manually tuned incremental DOM updates were appropriate in the beginning, when we were using jQuery to target slower devices/browsers. Each change to the DOM was expensive, and JavaScript code was slow to execute. Everything had to be deliberate. But it was costly. A lot of development time was spent manually synchronizing application state with the DOM. Have we rendered the template yet? If yes, don’t call render again - you’ll have to change things inside it manually!

All that goes away with React. Instead of direct DOM manipulation, your render() functions produce an intermediate data structure which represents the DOM as you’d like it to look. React diffs that with the existing DOM, and then makes only the necessary changes. Your app no longer has to think about synchronizing DOM state and application state.

This simplicity allows initial naive development, no or minimal performance concerns. Most of the time, this is fine. When performance optimizations are later needed, the tools are available. Re-use of DOM nodes via the key prop can provide a nice boost in some scenarios. And you can even do a little bit of extra work to tell React that a given subtree of your component graph doesn’t need a re-render at all.

2. Build-time errors with JSX

Developing for the web has long required near-constant refreshes of your HTML page. It made sense; you couldn’t really tell if your markup was well-formed until it hit the browser. This got worse with a framework like Angular or Ember: now you load the page, which loads the library, and then the library processes the HTML to find your directives. Typo in your directive name? Malformed loop syntax? The only way to know is to try it! Click the button and see if your logic fires!

Now, with JSX, a missing or mismatched </div> tag results in a build error! And because React components are Javascript code with JSX sprinkled about, linting can tell you if your attempt at a loop will run. Generally, there’s minimal magic involved here - JSX is a straightforward code translation, from <Tag></Tag> to React.createElement(Tag). It makes the whole thing easier to reason about.

Beyond that, basic unit testing of your React components gives you more confidence than with Ember or Angular, because you’re not missing the markup/directives half of your functionality!

Of course, there are still many scenarios where loading the page is required. Here React provides specific friendly error messages in development mode. And when you use a React component, the component’s specified propTypes can warn you about missing or malformed props.

3. Flexible rendering

Your first experience with React will likely be in the browser - an initial render, and then a lot of small updates the DOM as the user interacts with the application. But React has two key additional forms of rendering available:

Extremely innovative things are happening in both of these spaces. It’s quite exciting to see.

4. Lightweight

Some of the most performance-minded lately have started to question whether frameworks are worthwhile, especially in the mobile space. In particular, Android devices seem to run javascript quite slowly. It’s not the latency or download time - it’s the parsing and running. We’ve assumed that things are always getting faster, and they may still, but we need to give today’s customers a good experience.

So, what we need for mobile (and performance in general) are smaller downloads, faster boot-up time, and intelligent use of resources. React has a smaller download and faster boot-up versus other frameworks. Take a look at the numbers - there’s a clear difference (via this gist):

Name GZipped Size
Angular 2 + RxJS 143K 766K
Ember 1.13.8 123K 486K
Angular 2 111K 566K
Ember 2.2.0 111K 435K
Angular 1.4.5 51K 143K
React 0.14.5 + React DOM + Redux 42K 139K
React 0.14.5 + React DOM 40K 133K

5. You will conform!

As we explored above, React has a very specific way of doing things. There are different Flux implementations, but the core data flow is the same. This consistency reduces the number of architecture decisions required for a given project, and decreases ramp-up time for a developer who has previously used React.

Additionally, everyone I’ve spoken to says that this is not just another hot library - it’s a radical rethinking of the way user interface is done. And it doesn’t just feel warm and fuzzy. When features are reimplemented with Flux, longstanding tricky bugs just go away.

The Cons

As always we need to temper all the excitement with a little bit of reality.

  1. You will conform!
  2. Breaking changes
  3. Batteries not included
  4. It’s new

1. You will conform!

Yes, it is a double-edged sword. It’s not necessarily easy to re-train yourself in the way of React. The longer you’ve been writing web applications, the harder it is wrap your mind around it all.

The old is gone - you can no longer sprinkle jQuery around for the odd tricky situation. And the new is uncomfortable. When I last taught Flux, my students struggled with how much code it took just to update one textbox. I didn’t like JSX when I first encountered it.

Once you’ve internalized all that, it’s time to start thinking about your existing functionality and third-party libraries. What do you reimplement, what do you keep in place? You’ll need to pay particular attention to anything that attempts to modify the DOM itself. React is very jealous about the parts of the DOM it manages, but you can explicitly tell it to back off.

2. Breaking changes

React is not yet at version one. I’ll say it again - all version numbers still start with zero! In the world of semver, that means breaking changes can happen at any time. And they do. For example, with the recent release of 0.14, React split in two: the core react library and the web-specific react-dom library. Big changes like this are still happening, because the project is evolving quickly. react-native was first released less than a year ago!

The good news is that React is being used in production by Facebook. And not as a toy. They claim that they have 15,000 React components in their codebase. Therefore, the community understands the cost of breaking API changes, and does its best to help out. Deprecation warnings show up in versions prior to the change, and when the changes are in place, so are codemods, which can help migrate a codebase.

3. Batteries not included

Angular comes with a component for making AJAX requests, React doesn’t. Angular comes with an implementation of promises, React doesn’t. Angular has logging, React doesn’t. Angular has built-in routing. React doesn’t. Yes, a Flux implementation gets you closer to a web application framework, but you’ll still need to select your preferred library for all of these scenarios.

But that’s nothing new in the world of NERP, right? By now you’ve started to realize that the NERP stack is not all you need, it’s the backbone of the app you end up building - a place to start. You have the power to round out your application with whatever it needs: heavyweight or lightweight solutions.

4. It’s new

React was first released a little less than three years ago. It only broke through to the mainstream in 2015, and its search volumes still lag behind angular. Can you trust it? Will it just go away? Will you be able to find developers who know it well?

It seems to be getting more popular every day, but we can’t be sure. There is one thing we do know: React will eventually be replaced with the next hot thing. You’ll have to decide if you can get enough value out of it before then.

Conclusion: Jump in!

React is an innovative tool for building user interfaces in the browser, on the server, and on mobile devices. It’s not another framework that tries to provide the most value out of the box, or twist itself to work the way you work. You will conform!

But, like a strict personal trainer who has your best interests at heart, your applications will end up better off. Instead of spending time on syncing application state and the DOM, you can focus on features!

Full NERP ahead!

R is looking great! You can feel the momentum building - just one letter left to complete this new technology stack! Surely it will become one of the classics, known by all even if only the the lucky few can fully embrace it!

Next up: Part 4: P for Postgres


Fun fact: As of Feb 2016, this blog is statically generated with Node.js and React/React-Router.

I won't share your email with anyone. See previous emails.

NEXT:

P for Postgres (NERP stack part 4) 2016 Feb 22

Welcome to the fourth and final installment in my series (Part 1, Part 2, Part 3) delving into a new friendly (not MEAN), and perhaps even dazzling (but not a LAMP) development stack: NERP. Today... Read more »

PREVIOUS:

E for Express (NERP stack part 2) 2016 Feb 08

Welcome to Part 2 of my series (Part 1) about a new, nicer-than-MEAN, brighter-than-LAMP development stack. Today we turn to the Pros and Cons of Express. Read more »


Hi, I'm Scott. I've written both server and client code in many languages for many employers and clients. I've also got a bit of an unusual perspective, since I've spent time in roles outside the pure 'software developer.' You can find me on Mastodon.