When ReactJS was first announced in 2013, it was not an instant success.
At least, I personally took a glance and dismissed it quickly. I finally changed my mind just a few months later. I've now been using React for over 9 years and even created a popular newsletter called This Week In React.
But adopting React hasn't always been so easy. This article is not about the story of React, but rather a tale of my own experience of the early days, and the challenges I encountered.
To understand my perspective, it's important to give you some background.
Early in my career, I was a typical corporate Java JEE backend developer, using technologies like Spring, Hibernate, and dependency injection. After 3 years of experience on that stack, my goal was to grow my technical skills fast to have a more attractive developer profile. In 2012, I started contributing to a project for free, in my spare time, using all the newest technologies: Scala, MongoDB, ElasticSearch. This project later became a startup. I quit my job and became the CTO from 2013 to 2017. My position gave me the opportunity to assess React as soon as it came out.
Giving React a Second Chance
Even though React didn’t make the best first impression on me, Pete Hunt and a few others have been great ReactJS advocates (Rethinking best practices). We were willing to give ReactJS a second chance. At the end of 2013, we created 2 proof of concepts: one with AngularJS and one with ReactJS.
I worked on the AngularJS proof-of-concept. It was the natural, less risky choice for me. It was popular, full-featured, had a large community, and was appealing to many corporate Java developers due to its usage of dependency injection.
My co-CTO did the POC in ReactJS. He was a good functional programmer and tried to convince me of the superior model of ReactJS. It started to make sense to me: I really liked the idea of
View = f(State).
Learn more about the early days of React.js. Discover how it all began.
The 6 best frontend communities to join.
Adopting React - Not Without Challenges
In January 2014, we started our app rewrite on React 0.5.2.
At that time, we had to create components with a
It was already possible to share reusable React behaviors thanks to mixins and lifecycle methods.
This worked fine but occasionally you could encounter naming conflicts because the same variable name was used by 2 different mixins. Later, hooks somehow became the more composable successors of mixins.
There was no
React.memo either, nor
React.PureComponent, and we had to optimize React re-renders by hand, implementing a
Initially, React didn't bias too much toward functional programming, assuming developers may mutate state and call
this.setState to tell React to re-render manually. But if you avoided mutating state, it was possible to use a similar optimization to the one everybody uses today:
There was even an official mixin for that:
There was also no context API. At least, not officially. But there was this undocumented (at that time) legacy context API that we were advised not to use.
Also, there was no leading state management solution. At that time, we only had React local state, and everyone was trying to create their own state manager using the secret “do_not_use_or_you_fill_be_fired” legacy context above to solve the elephant in the room: props drilling. Using this API directly in your app remained uncommon, but it has proved to be successful and easier to use behind an abstraction.
Facebook introduced Flux. That architectural pattern looked interesting, but the proposed implementation looked a bit awkward and the community didn’t settle on it. Many pointed out the relationship it had with backend concepts like Event-Sourcing.
The community took inspiration from Flux, Om, and functional programming concepts to create a myriad of state management solutions. It wasn't so easy to make a choice between Fluxxor, Flummox, Morearty, React-Cursor, Omniscient, Baobab, and many others. I am also guilty of creating my own Atom-React package, but still proud it had an early prototype of time-travel debugging before Redux.
Many really liked the idea of having a single global state object and tried to avoid local
setState calls. However, it quickly became clear that being too dogmatic in how you manage the state doesn’t lead to great outcomes.
Rendering your global state from the very top didn't scale very well. It led to maintainability issues due to props drilling, but also performance problems. Re-rendering your whole app whenever you type a single letter on a text input was quite expensive and made the app less responsive, even when carefully using
shouldComponentUpdate on all the expensive components. It was clear that we needed something better to allow connecting a global state to deeper React components and avoid re-rendering from the app root. The usage of the legacy context was quite common through React mixins.
The Advent of Redux
When Dan Abramov introduced Redux at React-Europe 2015, the community was quick to acknowledge it was the cleanest implementation of Flux out there, and also leveraged functional programming concepts like immutability and event-sourcing in an elegant way. Many of us deprecated our state management libraries and adopted Redux instead.
Redux significantly helped make many functional programming concepts mainstream and popularized the concept of the reducer, which later made its official apparition in React as a hook. Redux also greatly popularized the idea of Higher Order Components through its
connect function as an alternative to mixins to solve the props drilling problem.
Redux also set the foundations to create a whole ecosystem. The Redux DevTools was a good demonstration of something powerful you could build on top of it. This drove a new wave of innovations leading to the creation of many other interesting projects such as Reselect or Redux-Saga.
Whether you like it or not, Redux made history and federated the community. It was the first library to provide an elegant solution to many problems that all React developers faced.
The Way React is Designed
Comparing React to Angular, the 2 frameworks have very different stories and design philosophies.
Angular came out as a full-featured framework with strong opinions and best practices. Over time, this led to some poor initial design decisions due to the lack of pragmatic feedback and various annoying breaking changes. The innovation mostly happened within a small circle of developers instead of appearing organically in the broad community.
React took a very different approach. It didn’t try to solve all problems at once and let the innovations happen in userland. Yes, it was hard in the beginning, but retrospectively it was the right thing to do. Facebook could have pushed to add Flux, ImmutableJS, and other opinionated patterns to React core. Instead, they let our community take ownership and figure out collaboratively the higher-level primitives we wanted to work with.
The way React is designed over time reminds me a lot of the Extensible Web Manifesto. This document which is well worth reading explains how the web aims to be designed to prevent irreversible mistakes in web and browser API design.
Adopting React was challenging in the early days. There were no clear solutions to many common problems. Some APIs were less elegant than the ones we use today and take for granted. Our startup had to innovate, and we created our own "temporary" state management solution until the community settled on Redux.
Make sure to watch Honeypot's React Documentary if you want to know more about the early days.
Overall, the React programming model hasn't changed much over the years. Many old concepts still exist today in different forms.
Over the year, the React team has done a great job focusing on low-level primitives and good escape hatches first, allowing a good level of innovation to happen in userland.
Back to the future, we now talk about Concurrent Features, React 18, Suspense, streaming, and Server Components. New low-level primitives have landed! It's time again for our community to step in, innovate, and build on these primitives in ways that even the core React team hasn't thought of.
The next few years will be exciting. You can count on me to tell you about all the latest React innovations, through my newsletter This Week In React.