Why I'm excited about React.js
Abstract: Even after a bad experience with client-side MVC, I’m excited to try React (it’s totally different). The Flux pattern detangles client-side spaghetti and makes code which is more reusable and more easily reasoned about.
Updated Jan. 2016: I’m less excited now. Rails+Turbolinks with React (for complex forms only) is my current approach.
We picked Batman. Sadly, it didn’t work out.
While there was much to commend it, it is no longer used by its creators and we’ve moved away from it as well.
Which left me with the question: is client-side MVC a good thing for the kinds of apps I build?
Probably not. I’m beginning to think that if you are already using something like Rails, then building out a full single page application in a client-side MVC is just going to duplicate important logic. Specifically for us, the models were the most difficult to keep DRY. Models have a habit of being related to each other, and these associations and their persistence back to the server is difficult to get right.
When we started with client side MVC, we thought we would see performance wins and we certainly did, at first. But then the project grew in complexity, and the browser which we thought was very fast got bogged down. Although our servers appeared fine (average response time was skewed by the tons of quick requests), the actual experience for our users was degraded. You wouldn’t believe the number of times internal functions were getting called! Thousands and thousands and thousands of calls on the client side, we had to selectively start re-writing in plain jQuery to get out of the pit.
We also thought that there could be a clean separation between server and client…the whole API first approach…but there ended up being a lot of duplication in things like validation, persistence, and relationships. You often had to fix bugs twice…one on the “temporary” side and the other on the “permanent” side. Technically, we could have let some of these slide by having the permanent side complain and so forth…but then you reduce the gains of being “client side” and are really more hybrid (which is probably better than an SPA).
It can also be fairly argued we made mistakes. Definitely true, I don’t contend that. It’s tough to do things right the first time, and no matter what it was a great learning experience. If I did build another SPA, I’d do it very differently…but I don’t think I need an SPA anymore.
So why now am I excited about React? Is this going to be another approach that works for the first six months, but then struggles under necessary complexity?
I can’t speak to the future but I can say why I’m excited now. React is different. It’s not trying to do everything the others are in fact by, “questioning best practices” it is doing some things deliberately that others would describe as very bad.
And of course, the virtual DOM got lots of visibility as it clearly set it apart (at that time) from the rest. But the real value proposition for me came once I understood the Flux pattern.
Unidirectional dataflow results in a declarative style of programming that gives me the benefit of getting the truth out of the DOM (and thus avoiding the jQuery spaghetti) while simultaneously constricting mutation so the app can stay reasonable.
Let’s unpack that.
Data Flows in a Circle
In Flux when something changes via user interaction a one way flow is initiated which updates relevant stores and triggers the re-rendering of related views. Rather than having components talk to each other and thus increase the surface area on which we have to reason when we are trying to make changes additions or improvements, we replace that spaghetti with a nice neat circle. Much easier to think about.
Declarative Programming beats Procedural
When you are doing something with jQuery, you tend to think procedurally: clicking on this means telling those things about it changing the color over here updating a number over here and so forth. With React, you just state how any component should render itself given a set of input (called
props). So when I add functionality the surface area of possible side effects is tremendously diminished. In fact whole categories of possible errors go away: I’m not referencing specific DOM ids or classes, and I’m not assuming transient browser state is still the same from one mutation to the next. Instead I update the truth, and the DOM is reflected to match that new condition.
Truth is still out of the DOM
It was really nice not having my data embedded in markup tags, and I feel like React/Flux gives me enough to still accomplish much of the same thing. We’ll see though.
Anyway, I’ve written up a Shopping Cart example that will be fodder for the next several posts as I expand upon my novice understanding of React and Flux.
I hope it’s helpful!