If you are among those who’re wondering what the noise is all about, this article will bring you much-needed relief. So, grab some coffee ☕, lean back, and enjoy! Rapid changes and overnight tectonic shifts do not bother frontend developers. They’ve understood that resistance is futile, and have buckled up to learn a new CSS framework every year, a new JavaScript framework every week (because that’s how fast they seem to be mushrooming), and complete rewrites of personal and work-related web apps every two years. And yet, nobody was prepared for the mammoth change that Facebook’s React team brought with Hooks. Suddenly, React developers were being told that the old way of building applications with classes was not the greatest idea ever; and that they should now adopt this shiny, new, highly capable thing called Hooks. On the topic of whether everyone should rewrite their React app’s classes into Hooks, the React core team dissuaded them, arguing that it was too much effort. But they really pressed on the idea that class-based components are going into maintenance mode, and Hooks are the bright new future everyone wants. This left everyone scratching their heads. Hooks had a non-trivial surface area to cover, the mental model was turned upside-down, and the learning curve (with many “surprise!” moments) was steep. As of writing, 18 months after release, Hooks are becoming more or less a standard in React apps. Knowing them is a must for new developers (as is, sadly, knowing class-based components because they are in use in many recent/old projects). But the overall scene remains hazy; those who understand hooks somewhat have declared themselves “experts”, while the rest are groping in the dark. Among senior developers, almost all consider Hooks to be a much better solution, while a few say they are just another weapon in their stash. The crux is that the winds are blowing in the direction of Hooks and whether you like them or not, you’d do your career a huge favor by understanding them. Let’s move on to understand two basic things about Hooks: 1) what they are; and 2) why you need them. However, I feel like I must highlight the flow of this article. Normally it’d make sense to tackle the “what” of something new and only then move on to the “why“. However, since this is an article for confused React devs (or just frontend devs in general), I think it’s far more important to approach the issue by explaining what kind of problems Hooks solve. With that done, the tension in our minds will be dissolved, and we will know the philosophy and pragmatism behind Hooks. And then, convinced about the idea (or not, though that won’t help much if you wish to become/remain a React developer), we can go through an overview of what Hooks are.
Why were React Hooks created?
Hooks were not created just because some brilliant engineers at Facebook were getting restless. You see, React is something Facebook uses itself (and very heavily, too), so from day one, they have aimed to evolve React in the direction that best serves their needs (composable, high-performance frontend work). Having written and maintained tens of thousands of components, the React team decided that class-based components were not working out. Let’s look at various reasons (highlighted by Facebook and others) that made developers dislike class-based components. JavaScript classes are a lie. This is my personal complaint with the direction the core language is taking. JavaScript might look like a C-inspired, curly-braces language, but that’s where the similarity ends. But then, the ES5/ES6 version of the language tacked on “classes”. Suddenly, “modern” JavaScript code made developers from other languages feel right at home: Classes, sub-classes, inheritance hierarchies, constructors, getters, setters, static members (roughly speaking), the extends and new keywords — stuff that gives battle-hardened OOP architects mental orgasms (with all due respect to their experience and capabilities). Just as sticking “Java” in the language name (in its early days, when it was called LiveScript) worked as a brilliant marketing stroke, the keyword “class” was perhaps supposed to cement the position further and blend into the crowd of languages that are very similar to each other (PHP, Perl, Python, Ruby, Java — you can almost seamless transition from one to another). But classes are a lie (of the “damned” type) in JavaScript. When a JavaScript engine runs code, it has no notion of classes; thus, a tool like Babel is needed to convert “modern”, “nice-looking” classes into plain functions. If there’s inheritance involved, it gets converted to the only type of inheritance possible in JavaScript — Prototypal Inheritance. So, when we close our eyes and write class-based code, we’re lying to ourselves and making our position weaker for the eventual day when our superficial knowledge will bite us back. Well, this is tricky! Despite the brave attempt at hiding the fundamental keyword this in JavaScript, the issue crops up often in React classes (and JavaScript classes too, in general). In several use cases, the component functions throw errors because they are not bound to the right context at that moment of execution. To solve this, you have to bind() them (read this for details) early on to the React context explicitly, or use arrow functions for callbacks. It’s not a deal-breaker for sure, but it does increase the cognitive burden by adding yet another thing to be aware of at all times; and of course, it’s the pit into which every new React developer falls. Much ado about something Code reuse is a common goal in software development. Classes might promote code reuse in other contexts (and languages), but in React, they introduce problems in code sharing. This was a major point of debate/interest early on in the React world, and the community finally evolved solutions like Higher-Order Components and Render Props to deal with it. The basic idea is that components are passed to other components, which “wrap” some functionality around them. Anyone who has touched code using these “solutions” knows the pain and doesn’t want to do it again (myself included). You only need to read through the official documentation for Higher-Order Components to see for yourself how unwieldy the whole idea is. In real-world projects, multiple code pieces often need to be shared, which can easily result in several layers of component-wrapping hierarchy. It’s the kind of code that even its author won’t understand after a few weeks! Yes, while code reuse isn’t impossible when using React classes, it’s clunky and confusing. Prop drilling Prop drilling is the problem you face (in vanilla React, at least) when you have a prop high up in the component hierarchy, and it needs to be made available to a component way down. Here’s an example: consider the user profile in a typical web app , which is usually shown in the header. Now, let’s suppose that the user’s details are also needed in the footer component, perhaps to say something like “You’ve made 34 transactions till now | Get more interesting stats here”. How to make the profile info available down in the footer if you’re using classes? Well, some React developers I know would say “screw it!” and make an extra API call in the footer too, but this is a terrible practice. The only approach that comes to mind also happens to be the only option: keep passing the profile prop down from component to its child component until it reaches the footer component. Yes, it’s a tedious process, and yes, it makes the code hard to read (because in the in-between components, you need to mentally keep ignoring the prop as it has no use except simply being on the way down). This top-down chained handling of a prop is called prop drilling and is a dreaded phenomenon in the React world. When using classes, React devs would solve it using something like Redux, but that’s too much upfront investment if you’re not going to use Redux for everything. With Hooks, React has released a feature called Context that was tailor-made for this use case. Now, Context can be used with classes as well, but it’s hard to ignore the clunkiness; also, with Hooks, consuming multiple contexts is a breeze. Fewer things to learn This can sound paradoxical, and the React team acknowledges the argument. A completely new way of writing React apps are being introduced; we are being told that we shouldn’t rewrite or throw away the existing class-based code, and yet the React team tells us that there are fewer things to learn! Actually, the thing is, in the short-term, the overall complexity and confusion in the React ecosystem will skyrocket (and it has, as new people learning React need to learn Classes, HoC, Hooks, Context, Redux, and many other libraries as well as their corner cases). But the larger point is that if Hooks turns out to be a successful concept, in the long term, a large number of concepts can be dropped, leaving us with a small core of Hooks, functional components, and not much else. It’s not happening anytime soon (simply because of the amount of existing code based on classes), but it’s where we will eventually end up. Sensible component “upgrade” A common dilemma in React has to decide whether a new component should be written as a class or as a function. To minimize complexity, the common practice has been to start with a stateless functional component. Then, if a time comes when you think that the component in question needs to manage some state or needs access to more functionality (lifecycle methods, for example), you convert it into a class-based component. Except that you need just to delete all the component code, rethink the approach, and then write a class-based version. Not fun, yes. With Hooks, such component “upgrades” are easier and smoother: a functional component remains a functional component even after taking on many duties; lifecycle methods do not feature in Hooks, though some similar functionality is available; finally, any common functionality can be extracted into separate hooks and reused by other components. Did you spot the beauty in this case? — everything is either a function or a Hook (which is also a function, but we can make the distinction for the sake of development), and there’s no monkey business involved when trying to fit a square peg in a round hole. 😀 So, there we have it. Hooks are not aimed at any one thing but are a major paradigm shift. It’s inconvenient, yes, but the resulting developer experience is far better (as compared to React with classes). Now that we have dealt with the “why”, let’s turn our attention to what Hooks really are.
What are Hooks in React?
Hooks are tough and very easy to define at the same time. The easy version is what you’d find in the initial sentences of the official docs: Hooks are a way of writing React components without classes; they also provide you ways to “hook” into the React core features such as state, controlling re-renders, etc., in functional components. That didn’t help much, right?! Because it didn’t help me the first time, I came across Hooks. To understand what Hooks really are, you have to go on a long and patient study of their ins and outs (and there’s no shortage of them!), build applications using them (maybe even rebuild past applications), get bitten by special cases, and so on. But just to give you a “feel” of it, here’s what code with Hooks looks like. Remember, all components are functional, and the code relevant to a component is defined inside it. Yes, it’s the same Counter component we all have written umpteen times while using classes! But you can see how drastic the differences are: the constructor disappears, accessing and changing state is much simpler and modular (you can have as many useState() invocations as you need for managing different pieces of state), and the code is shorter. In several cases, the resulting code is much shorter than a class-based component — simply because Hooks capture and provide the same functionality succinctly. There are several types of hooks, and useState() is just one of them. If you’re curious about how many there are and what they do, take a look at the official docs. Conclusion Hooks bring enormous changes to the React ecosystem and are here to stay. They simplify the component structure, architecture, hierarchy, code reuse, and much more. While there are some extremely vocal critics, the overall reception has been very warm, and the future looks hopeful. This is one of those fundamental contributions by the React team that is likely to impact other frameworks and influence front-end development fundamentally. Next, please find out how to get it started with React Storybook.