We used to believe many things to be true. We believed the sun orbited the earth. We believed the plague was a punishment from the gods. We believed that Model-View-Controller architectures and two-way data binding were the best ways to structure user interface programs on the web.
All these beliefs were true to those who believed them at the time, as we didn’t yet have better ways to reason about the world.
Eventually, astronomers proved the heliocentric solar system, doctors discovered the microbial theory of disease, and React introduced us to the concept of unidirectional data flow.
None of these discoveries were immediately universally accepted. Galileo was tried for heresy. Dr. Semmelweis, who discovered the germ-based origin of diseases, was driven insane by his peers’ refusal to accept his research and died in an asylum. And still today, we haven’t yet agreed that not all UI architectures are created equal.
I strongly believe that React — or something like it — is the future of user interface development. But before you scroll to the end of the article to post an angry comment (or 👏 because you happen to agree), let me tell you why.
React is a collection of clever ideas created by extremely clever people. When React was first announced, the selling point people used to talk about was its rendering approach — the idea that if we separate the representation of our application structure from the underlying rendered DOM, we can achieve a declarative view rendering syntax while still applying optimal DOM mutations.
This was paired with other controversial ideas, the main one being the insight that separating code across technology boundaries — HTML, JavaScript and CSS — is not real separation of concerns. In order to create programs with high internal cohesion and low external coupling, we’re better off colocating the presentation, behaviour and state of a piece of UI in a single file in JavaScript. This approach has the unfortunate side effect of making UIs hard to author in plain JavaScript, and thus React shipped with a language syntax extension called JSX.
If you’re not a web frontend developer, it’s really hard to understand how anyone can get upset over a language extension, but web is a weird place, and some people sure did.
Premium vintage HN hot takes after React’s announcement
Naturally, nobody likes being told their core beliefs are wrong. And so, among the blowback and the conceptual novelty, the core value of React still often gets forgotten.
React, at its core, is all about its components. The Virtual DOM is a cool piece of technology, but it’s only an implementation detail — if React could’ve been created without it, it wouldn’t need to even exist. JSX is a clever hack, but it’s only syntax sugar on top.
By now components are a well-established concept, and they did exist before React. The Web Components specification was already standardised when React was released. Much like Galileo wasn’t the first to discover heliocentricity, React didn’t invent components — it just found the right recipe for them.
React components are all about their composability and encapsulation. In addition, they benefit from being functional and multi-purpose. Let me break down what that means:
This small and focused component abstraction gives us all the qualities we as developers seek: it’s easy to learn and remember, ergonomic to use, and results in programs that are possible to maintain and collaborate on.
But there is one more quality of components that I haven’t talked about yet, and that, it turns out, is the most important one.
I began this article by praising the virtues of React, but I’m happy to admit React is not perfect; there are still tons of missed optimisation opportunities that the React core team is actively working on, and new ideas are constantly discussed, implemented, and discarded. When you look at the larger ecosystem of libraries, patterns and practices around React, they’re even further from perfect. We can’t even decide if composition should be done with Higher-Order Components, Render Props, Functional Children Props, or, god forbid, with Component Components!
While the wealth of options can sometimes be fatiguing, it is in fact a perfect example of the true strength of React’s component model. By having a universal, small, composable, flexible and reliable building block, we are able to discuss, test and accept new ideas without having to discard all our existing work.
It’s absolutely crazy to me that individual developers on different sides of the world can build revolutionary libraries like Redux, Apollo or styled-components, and application developers can adopt each of these new tools alongside their existing toolset without having to modify their existing code, or replace each individual piece without having to throw the baby out with the bathwater.
Each of these libraries do complicated things outside the React sphere, but none of them step on each others’ toes, because each of these tools can take advantage of the component composition model. Thus, the React component model is not only a user interface primitive — it’s an innovation primitive.
Unlike a progressive sprinkling of JavaScript, React can adopt new tools without having to refactor massive amounts of code thereby making their adoption infeasible. And unlike monolithic frameworks like Ember or Angular, React has sufficient flexibility to not snap when bent by the forces of inevitable change.
Having a platform that adapts to change is paramount, because change is inevitable and revolutions are expensive.
Smart people won’t suddenly stop seeing problems in the world and coming up with solutions for them. People won’t stop being frustrated by the constraints that exist, and won’t stop trying to break free. We as a developer community won’t suddenly stop wanting to adopt better tools when they are discovered. No matter how hard you want to bury your head in the sand and hope things stay the way they are, progress can’t be stopped.
When change happens, the best you can hope of a system is that it can adapt to change, because the only alternative is an unthinkable tragedy.
After the framework wars of the last decade, we now live in a time of unprecedented productivity, prosperity and peace. Tools like React allow us to build and maintain ambitious products.
If our tools stood in the way of progress, we would eventually have to discard them to move forward. And the cost of revolution is ruination: we would have to replace all our libraries, relearn all our good practices, retrain all our teams, repeat all our mistakes, and rewrite or refactor an incredible amount of code, instead of focusing on the products we were creating.
Innovation moves at two speeds:
Revolutions are rapid, refinement is slow.
React was a revolution. It overthrew the status quo of best practices of its time and provided us with a significant improvement in developer experience almost overnight. Now we’re fine tuning the engine until we can no longer squeeze more juice out of it. The refinement phase of the innovation cycle will eventually plateau, and will no longer be able to demonstrate the year-on-year progress that we’ve become accustomed to.
But the curve is not a fixed function. We can keep innovating and creating, as long as we as developers make decisions that keep our ecosystem responsive to change.
No matter whether we’re working inside the React ecosystem, using another framework, building frameworkless progressive web applications, or even building software not related to the web platform at all, we can follow these lessons learned from React and its ecosystem to make the code bend instead of snap when faced with change.
I believe React is the obvious choice for building ambitious user interfaces that will be able to stand the vagaries of progress.
While I’ve underplayed the importance of Virtual DOM, it has proved to be one of the most future-friendly features of React. Because of the separation of the virtual representation and the implementation of your UI, React is well-suited for server side rendering and universal web applications. Native mobile platforms are an undeniable part of user interface development; React Native can help us there, and recoil gives us an exciting glimpse of what React could look like in native Kotlin and Swift. ReasonML and ReasonReact can help us move the React paradigm to platforms further than JavaScript can reach. With augmented and virtual reality technologies looming large in the future, there’s a threat of storm in the air, and I hope React VR and other similar experiments can help us weather it.
Eventually, React will be replaced by something else. We don’t yet know what the forcing function will be — WebAssembly, perhaps — and we don’t know what comes next. Whatever it is, I look forward to it with a mix of trepidation and excitement.
For now, thanks to React’s resilience, I’m confident we will get to enjoy our period of peace, prosperity and productivity for a while longer.
If you want to read more of my musings at the intersection of technology and comedy, follow me on Twitter.