On the Origin of React

Rate this content

This talk looks at how components in React have evolved. We'll look back at previous versions of React, the headlining features, and how milestones like Fiber and Concurrent changed how we wrote React components. Some more details: I want to give attendees a glimpse of how React components looked at different major points in the history of React. Components written in 2013 don't look like components written in 2015 or today. This is a history of React that for some will be a walk down memory lane and for others, completely new information.

22 min
25 Oct, 2021

AI Generated Video Summary

This Talk explores the evolution of React components, starting from version .12. It discusses the introduction of class components and the deprecation of mixins. It highlights the emergence of higher-order components as a better option for code reuse. It also covers the introduction of hooks in React 16.8 and mentions potential future branches of evolution, such as server components and function components in hooks.

1. Introduction to React Evolution

Short description:

Welcome to On the Origin of React. I'm Jen Craden, a senior software engineer at Netflix, here to talk about the evolution of components. React borrows from On the Origin of the Species, and just like Darwin's finches, React components have evolved and adapted. This talk provides context on older React structures and explains what's changed and why.

Hi y'all, welcome to On the Origin of React. I'm Jen Craden, and I'm a senior software engineer at Netflix, where I work on the Node.js Platform team. So, I'm here today to talk to you about evolution. Well, the evolution of components.

So, this talk borrows its title from On the Origin of the Species, one of the most well-known books in modern history. And when you see this book, or the name Charles Darwin, who wrote it, the word evolution probably comes to mind. Or maybe it's natural selection. Or if you're me, it's finches. I always think of Darwin's finches.

Now, all of these are fair associations, and actually all related. So, evolution is based on natural selection, and Darwin came to the idea of natural selection during his travels to the Galapagos Islands. Where he observed finches. All the same, but uniquely different. So, it's the beaks, each adapted to a specific food type. Seeing this graduation and diversity of structure in one small, intimate-related group of birds in this archipelago, one species had been taken and modified for different ends. Those are the finches. But this graduation and diversity of structure, this one species taken and modified for different ends, maybe that could be React components, too.

You see, we're at a point in React's history now where we can actually look back and see how it evolved. I promise you this isn't a history lesson. We're not gonna be memorizing dates or discussing the great RFC debates of 2016 or what have you. This talk is meant to be useful. Older versions of React are still in production. And depending on when you learned React, you might look at a component from a previous version and have some questions. That's where this talk comes in. It'll help you identify some of the older structures and provide context on what's changed and why. Now, if you've been writing React since the early days, this talk is more of a trip down memory lane. That's how I felt writing it. I've been working with React since version .12 and that was released in late 2014. At that point, React had been publicly available for over a year. Its initial public release was in mid-2013.

2. React Components Evolution

Short description:

React components around version .12 marked the starting point. This period served as the baseline for component structure and behavior. React.createClass was used, as class and function components, as well as fragments, did not exist. Lifecycle methods, such as component will mount and did mount, remained consistent. Code reuse was achieved through mixins.

But I don't consider that our starting point. We're actually gonna start to look at React components around version .12. Again, this is when I started learning React and that's because React was actually becoming a thing. So it was starting to gain traction in the JavaScript community, React was the buzzword.

Also, there aren't significant changes to React components between .3 and .12. So this period of time is our baseline for how components were structured and behaved. And this is one of those components. Now, some of you have never seen this before and some of you are experiencing flashbacks, but yep, this is React in its early days.

Now, the first thing you probably notice is React.createClass. So at this time in React's history, class components don't exist. Neither do function components. We also don't have fragments and there are extra spans being rendered. That is true. And there is so much more. I'm not going to be able to list out all the differences in React and its ecosystem between then and now, but for a component structure, this is our earliest ancestor.

So as we start to build an evolutionary tree of React components, this becomes the base of the tree. All components from here out evolved from CreateClass. And those evolutions follow some common branches. So if we're looking at this component again, what attributes evolved along with component structure? Well, besides the creation of the component itself using CreateClass, what about lifecycle methods? Here I've stubbed out all the lifecycle methods available to us in React.12 and earlier. So that's component will mount, component did mount, will receive props, will update, did update, will unmount. Now, these are likely more familiar than CreateClass itself, and that's because these lifecycle methods do not change for a large part of React's history. You've probably seen these or worked with these life cycles at some point. Less familiar to you might be getInitialState and getDefaultProps, and these do exactly what you would expect, set the initial state or set the default props. So it's an unfamiliar structure but a familiar concept. Filling out the branches on our tree, life cycles become one of those branches. We're going to keep an eye out for how these life cycles evolve over time in tandem with component structure.

Now, there's one more branch on this evolutionary tree to explore, and that's code reuse. How do we share code between components? Well, back in the day of createClass, we used something called mixins. So here's a mixin. It looks remarkably similar to how we create components, but we don't pass this object to createClass.

3. React Components and Code Reuse

Short description:

We're going to provide mixins to components for code reuse. Class components were introduced in version .13, bringing a fundamental shift in building React components. They extend from React.component instead of using createClass, and state is set in the constructor while DefaultProps is a class property. Class components don't support mixins, marking a slow start in evolving code reuse in React.

Instead we're going to provide it to a component with the mixins key and an array of mixins. So here I'm providing the countMixin to this component. And now I can use what's provided in the mixins as if it existed in the component itself. I'm using this.increment, part of the countMixin, and this.state.count, also part of the countMixin. So now we can fill in the code reuse branch of our tree with mixins as the first evolution in that branch. It doesn't take long, by the way, for this tree to grow.

So the next version of React builds on this base and we're going to start to see more familiar structures like class components. Class components are introduced in version .13. This is a big deal. So it's a fundamental shift in how we built React components. Now, createClass is still supported, but soon classes are going to become the default. And we're not going to spend too long looking at class components, but I want to point out a few key differences from createClass. The first being that we don't call createClass. Instead, we extend from React.component. Now, getInitialState and getDefaultProps are also no longer. We set state in the constructor and we set DefaultProps as a class property. Okay, so let's add class components to our tree. These are a direct evolution from createClass. Ah, but what about the other branches? Did anything change? In terms of life cycles, really nothing. As mentioned, initializing state and DefaultProps is a bit different, but the lifecycle methods themselves are still there. So, class components are still connected to the lifecycle branch. What about code reuse? Are we still using mixins with class components? No. So, class components don't support mixins. And this turns out to be the slow start of evolving code reuse in React. So, evolution tends to be a slow process. Natural selection happens generation to generation, small changes, adaptations allow species to survive and pass those traits on to the next generation. Now, peppered moths are a famous example of natural selection and action. Somehow over the course of 50 years, starting in the 1850s, the previously light colored moths changed colors. By the early 1900s, dark peppered moths were the dominant population. What's fascinating is why the moths changed colors, what else was happening during those 50 years? It wasn't the moths alone that were evolving.

4. React Evolution and the Deprecation of Mixins

Short description:

The industrial revolution forced evolution on species. Mixins weren't deprecated in React until version .13, but class components without mixins pushed React to evolve past them. Function components were introduced as a simpler syntax for existing components, embraced by the React community. However, they lacked lifecycles and code reuse options. A blog post titled 'Mixins Considered Harmful' in 2016 signaled the upcoming deprecation of mixins in React.

The industrial revolution meant factories were built, factories that ran on coal that produced a dark smoke that coated the landscape, so light peppered moths were less able to camouflage themselves. Predators were able to spot them against the darker landscape, and their survival rate dropped, but the dark peppered moths, their survival rate increased. So sometimes natural selection is just sort of happenstance, a mutation that happens to be an improvement on the previous version, but sometimes evolution is forced on a species.

And I should be clear that forced doesn't imply intent. Mixins weren't even deprecated in version .13, and there wasn't intent to deprecate mixins in future versions. The rule was simply if a mixin is required, use create class. Class components were meant to evolve, react closer to idiomatic JavaScript. Mixins weren't part of JavaScript, so it made sense not to include them. Now, the lack of support wasn't meant to push React away from mixins, even though that is what happened. It wasn't intentional, but class components without mixins did force us to evolve past them.

Evolution is a slow process though, so before that happens, we have a new development in React. Stateless components, or as we refer to them now, function components. So stateless just wasn't the best term for these because components without state already existed. You could create a component with only the render function. Lifecycles, state, and even props are still 100% optional in React components. So it's better to describe these for what they are, function components. These are introduced as a new, simpler syntax for the components we were already writing, and I have to say, these are beautiful. When these are released, it is lovely. Even better with destructuring props, like, ooh, look at that, it's so gorgeous. When these are released, the React community fully embraces function components. These are a welcome addition to React's evolutionary tree.

Now, at the time, there are no life cycles in function components and no options for code reuse. Like class components, function components move React closer to idiomatic JavaScript. So this evolution makes sense. But now we have create class, class components, function components, and create class is still a requirement for mixins. That's gonna change soon. Actually, it's been in the works for a while. In early 2016, a new blog post is published to the official React blog. Its title is, Mixins Considered Harmful. Okay, what happened? So as of .13, mixins aren't deprecated and are gonna be deprecated, so what changed? Look, mixins weren't a great solution to begin with.

5. Evolution of Code Reuse in React

Short description:

Mixins in React were initially used as an escape hatch but as React evolved and composition became popular, mixins were found to be harmful. Higher-order components (HOCs) emerged as a better option for code reuse, providing additional functionality to components. HOCs, although having some issues like naming collisions, offered a compositional approach to code reuse in React. With the introduction of higher-order components, React was on its way to becoming modern. React version 15 was skipped, and version 16 introduced fragments, error boundaries, portals, and more.

They suffer from problems with indirection, maintenance, and most importantly, breaking composition. Composition is a core React concept. Now, this blog post is still around if you wanna read it, but the too-long-to-read is. Mixins weren't meant for this. They were meant as an escape hatch. Three years have passed since React was released. The landscape has changed. Multiple Vue libraries now adopt a component model similar to React. Using composition over inheritance to build declarative user interfaces is no longer a novelty.

Mixins weren't considered harmful earlier in React's history but as React became more popular, as composition was adopted, as the users of React leaned into composition, we realized that mixins were harmful and that we didn't need the escape hatch they provided. There were better options that fit with React's compositional model, like higher-order components. So a higher-order component is a function that takes a component and returns a new component and that new component is often provided extra functionality so this function withCounter is a higher-order component and by the way, that is a mouthful so I'm gonna start to call them HOCs. This HOC takes in a component and provides a count and a function to increment that count.

So here is a button component that expects an increment function and a count and here I provide the button component to the HOC and I'm returned a new counter button with all the functionality that I need. This is a super contrived example but that's the gist. HOCs still have issues like naming collisions but we now have an option for code reuse with class components and it's compositional. Now we can add higher order components as the next generation of code reuse in React. I know it doesn't feel like it but with that addition, we're actually really close to modern React.

Closer than you might think. This tree actually doesn't change for a long time. React's next major release is version 15. Yeah, I know. We went from .14 to 15. Previous versions of React were meant to build to a stable 1.0 release but React was stable. And it had been for a while. So we just went to 15. And 15 has lots of updates but nothing that fundamentally changes component structure. So we're going to skip it and head to the next major release. Version 16. So its initial release, 16.0 introduces fragments, error boundaries, portals, and more.

6. React Evolution: Life Cycles and Hooks

Short description:

16.3 and 16.8 introduced life cycle deprecations and hooks. Fiber, React's reconciler, allowed for pausing and resuming work, making some life cycle methods unsafe. New life cycle methods were introduced to handle these changes. Hooks are an evolution of function components, providing a new option for code reuse. The timeline ends with React 17, which has no new developer-facing features.

But no real changes to components or life cycles until a little bit later. So I refer to 16.3 and 16.8 as two major releases that weren't major releases. Technically, these are minor releases but these are when life cycle deprecations are introduced and hooks are available. So the life cycle deprecations are a bit jarring. Remember that React was introduced, that since React has been introduced, there have been no significant life cycle changes, but in 16.3, three life cycles are marked as unsafe. The life cycles themselves aren't removed, but to use them, you now you need to use the unsafe prefix.

And so this is for component will mount, will update and component will receive props. Now, why these changes and why now? The answer is Fiber. So Fiber is React's reconciler, and I'm gonna explain it to you very, very fast. If you're interested in this, there are tons of more in-depth resources, but to contextualize these life cycle changes, here's what you need to know. Before Fiber, the reconciler used recursion, but recursion doesn't allow you to stop and start a process. Fiber can, so React can do some work, pause, let the browser do some work, and then resume its own work, and so on and so forth. And because work can be paused and resumed, some life cycle methods were unsafe. We expect that component will mount will be followed by component will unmount, but with Fiber it's possible that component will mount could be called multiple times, and component will unmount wouldn't be called at all. So the work can actually be stopped before the component mounted, and that's why it's unsafe. To help with these changes, new life cycle methods were introduced. So that's get drive state from props, and get snapshot before update. I'm not gonna spend time explaining these, there's great documentation out there if these are unfamiliar to you, but these are the first new life cycles in all of react's history, and this is also the last evolution on that side of the tree. The side more centered around class components, life cycles, HOCs. As our timeline moves forward, hooks are introduced.

And again, I'm not gonna explain hooks, but these are an evolution of function components. So now we can use state and function components, and there are other hooks that allow us to hook into the capabilities previously scoped to class components alone. You'll notice though that I don't connect the lifecycle branch to hooks. And that's because the hooks aren't life cycles. There are no real life cycles in function components, that's the future of react. Use effect might run once, a cleanup function might be provided, but those aren't life cycles. Hooks are also a completely new option for code reuse that isn't even related to HOCs or mix-ins, it's a new branch all on its own. And just like that, we're at the end of the timeline. It came up fast, I know. 17 is released with no new developer facing features, and here we are at modern day React.

7. React Evolution: What's Next?

Short description:

Our evolutionary tree remains unchanged. The React team's research on server components and function components in hooks could be potential branches for future evolution. As we move forward, we may forget how things used to be, but it's an exciting journey to see how far we've come. Thank you all for listening.

Our evolutionary tree remains unchanged. This might make us wonder, what's next? I have guesses, I mean, the React team shared their research on server components last year, that could be a branch on this tree. Or looking at function components in hooks, that part of the tree is kind of bare, so maybe that's where we'll see some evolution.

The truth is, I don't really know. What I do know is, in writing this talk, I realized how I'd forgotten just so much about early React. I guess that's the benefit of being able to move forward without looking back. And if you're new to React, it's gonna happen to you one day too, you're gonna forget how things used to be.

Oh, and I can't wait for that moment for you, because it wasn't just React evolving in that time, it was you too. And you're gonna get to see how far you came. And with that, I just wanna say, thank you all for listening. I'll see you online in one day in the real world too.

Check out more articles and videos

We constantly think of articles and videos that might spark Git people interest / skill us up or help building a stellar career

React Advanced Conference 2022React Advanced Conference 2022
25 min
A Guide to React Rendering Behavior
React is a library for "rendering" UI from components, but many users find themselves confused about how React rendering actually works. What do terms like "rendering", "reconciliation", "Fibers", and "committing" actually mean? When do renders happen? How does Context affect rendering, and how do libraries like Redux cause updates? In this talk, we'll clear up the confusion and provide a solid foundation for understanding when, why, and how React renders. We'll look at: - What "rendering" actually is - How React queues renders and the standard rendering behavior - How keys and component types are used in rendering - Techniques for optimizing render performance - How context usage affects rendering behavior| - How external libraries tie into React rendering
React Summit Remote Edition 2021React Summit Remote Edition 2021
33 min
Building Better Websites with Remix
Remix is a new web framework from the creators of React Router that helps you build better, faster websites through a solid understanding of web fundamentals. Remix takes care of the heavy lifting like server rendering, code splitting, prefetching, and navigation and leaves you with the fun part: building something awesome!
React Advanced Conference 2022React Advanced Conference 2022
30 min
Using useEffect Effectively
Can useEffect affect your codebase negatively? From fetching data to fighting with imperative APIs, side effects are one of the biggest sources of frustration in web app development. And let’s be honest, putting everything in useEffect hooks doesn’t help much. In this talk, we'll demystify the useEffect hook and get a better understanding of when (and when not) to use it, as well as discover how declarative effects can make effect management more maintainable in even the most complex React apps.
React Summit 2022React Summit 2022
20 min
Routing in React 18 and Beyond
Concurrent React and Server Components are changing the way we think about routing, rendering, and fetching in web applications. Next.js recently shared part of its vision to help developers adopt these new React features and take advantage of the benefits they unlock.In this talk, we’ll explore the past, present and future of routing in front-end applications and discuss how new features in React and Next.js can help us architect more performant and feature-rich applications.
React Advanced Conference 2021React Advanced Conference 2021
27 min
(Easier) Interactive Data Visualization in React
If you’re building a dashboard, analytics platform, or any web app where you need to give your users insight into their data, you need beautiful, custom, interactive data visualizations in your React app. But building visualizations hand with a low-level library like D3 can be a huge headache, involving lots of wheel-reinventing. In this talk, we’ll see how data viz development can get so much easier thanks to tools like Plot, a high-level dataviz library for quick & easy charting, and Observable, a reactive dataviz prototyping environment, both from the creator of D3. Through live coding examples we’ll explore how React refs let us delegate DOM manipulation for our data visualizations, and how Observable’s embedding functionality lets us easily repurpose community-built visualizations for our own data & use cases. By the end of this talk we’ll know how to get a beautiful, customized, interactive data visualization into our apps with a fraction of the time & effort!

Workshops on related topic

React Summit 2023React Summit 2023
170 min
React Performance Debugging Masterclass
Featured WorkshopFree
Ivan’s first attempts at performance debugging were chaotic. He would see a slow interaction, try a random optimization, see that it didn't help, and keep trying other optimizations until he found the right one (or gave up).
Back then, Ivan didn’t know how to use performance devtools well. He would do a recording in Chrome DevTools or React Profiler, poke around it, try clicking random things, and then close it in frustration a few minutes later. Now, Ivan knows exactly where and what to look for. And in this workshop, Ivan will teach you that too.
Here’s how this is going to work. We’ll take a slow app → debug it (using tools like Chrome DevTools, React Profiler, and why-did-you-render) → pinpoint the bottleneck → and then repeat, several times more. We won’t talk about the solutions (in 90% of the cases, it’s just the ol’ regular useMemo() or memo()). But we’ll talk about everything that comes before – and learn how to analyze any React performance problem, step by step.
(Note: This workshop is best suited for engineers who are already familiar with how useMemo() and memo() work – but want to get better at using the performance tools around React. Also, we’ll be covering interaction performance, not load speed, so you won’t hear a word about Lighthouse 🤐)
React Advanced Conference 2021React Advanced Conference 2021
132 min
Concurrent Rendering Adventures in React 18
Featured WorkshopFree
With the release of React 18 we finally get the long awaited concurrent rendering. But how is that going to affect your application? What are the benefits of concurrent rendering in React? What do you need to do to switch to concurrent rendering when you upgrade to React 18? And what if you don’t want or can’t use concurrent rendering yet?

There are some behavior changes you need to be aware of! In this workshop we will cover all of those subjects and more.

Join me with your laptop in this interactive workshop. You will see how easy it is to switch to concurrent rendering in your React application. You will learn all about concurrent rendering, SuspenseList, the startTransition API and more.
React Summit Remote Edition 2021React Summit Remote Edition 2021
177 min
React Hooks Tips Only the Pros Know
Featured Workshop
The addition of the hooks API to React was quite a major change. Before hooks most components had to be class based. Now, with hooks, these are often much simpler functional components. Hooks can be really simple to use. Almost deceptively simple. Because there are still plenty of ways you can mess up with hooks. And it often turns out there are many ways where you can improve your components a better understanding of how each React hook can be used.You will learn all about the pros and cons of the various hooks. You will learn when to use useState() versus useReducer(). We will look at using useContext() efficiently. You will see when to use useLayoutEffect() and when useEffect() is better.
React Advanced Conference 2021React Advanced Conference 2021
174 min
React, TypeScript, and TDD
Featured WorkshopFree
ReactJS is wildly popular and thus wildly supported. TypeScript is increasingly popular, and thus increasingly supported.

The two together? Not as much. Given that they both change quickly, it's hard to find accurate learning materials.

React+TypeScript, with JetBrains IDEs? That three-part combination is the topic of this series. We'll show a little about a lot. Meaning, the key steps to getting productive, in the IDE, for React projects using TypeScript. Along the way we'll show test-driven development and emphasize tips-and-tricks in the IDE.
React Advanced Conference 2021React Advanced Conference 2021
145 min
Web3 Workshop - Building Your First Dapp
Featured WorkshopFree
In this workshop, you'll learn how to build your first full stack dapp on the Ethereum blockchain, reading and writing data to the network, and connecting a front end application to the contract you've deployed. By the end of the workshop, you'll understand how to set up a full stack development environment, run a local node, and interact with any smart contract using React, HardHat, and Ethers.js.
React Summit 2023React Summit 2023
151 min
Designing Effective Tests With React Testing Library
Featured Workshop
React Testing Library is a great framework for React component tests because there are a lot of questions it answers for you, so you don’t need to worry about those questions. But that doesn’t mean testing is easy. There are still a lot of questions you have to figure out for yourself: How many component tests should you write vs end-to-end tests or lower-level unit tests? How can you test a certain line of code that is tricky to test? And what in the world are you supposed to do about that persistent act() warning?
In this three-hour workshop we’ll introduce React Testing Library along with a mental model for how to think about designing your component tests. This mental model will help you see how to test each bit of logic, whether or not to mock dependencies, and will help improve the design of your components. You’ll walk away with the tools, techniques, and principles you need to implement low-cost, high-value component tests.
Table of contents- The different kinds of React application tests, and where component tests fit in- A mental model for thinking about the inputs and outputs of the components you test- Options for selecting DOM elements to verify and interact with them- The value of mocks and why they shouldn’t be avoided- The challenges with asynchrony in RTL tests and how to handle them
Prerequisites- Familiarity with building applications with React- Basic experience writing automated tests with Jest or another unit testing framework- You do not need any experience with React Testing Library- Machine setup: Node LTS, Yarn