React Hooks were introduced in 2018 and ever since numerous POCs have been built around the same. Hooks come in at a time when React has become a norm and class components are becoming increasingly complex. With this blog, I showcase how Hooks can reduce the size of your code up to 90%. Yes, you heard it right. Exciting isn't it?
Hooks are a powerful upgrade coming with React 16.8 and utilize the functional programming paradigm. React however also acknowledges the volume of class components already built and therefore comes with backward compatibility. You can practice by refactoring a small chunk of your codebase to use React hooks while not impacting the existing functionality.
With this article, I make an attempt to show you how hooks can help you write cleaner, smaller and more efficient code. 90% Remember!
First, let’s list out the common problems we all face with React Components as they are today:
1. Huge Components - caused by the distributed logic in lifecycle hooks
2. Wrapper Hell - caused by re-using components
3. Confusing and hard to understand classes
In my opinion, these are actually symptoms of one big problem i.e. React does not provide a stateful primitive simpler, smaller and lightweight than class component. That is why solving one problem worsens the other. For example, if we put all of the logic in components to fix Wrapper Hell it leads to Huge Components which makes it hard to refactor. On the other hand, if we divide the huge components into smaller reusable pieces, it leads to more nests than in the component tree i.e. Wrapper Hell. In either case, there’s always confusion around the classes.
Let’s approach these problems one by one and solve them in isolation.
Huge Components -
We all have used lifecycle hooks and often with time these lifecycle Hooks contain more and more stateful logic. It is also observed that stateful logic is shared amongst lifecycle hooks. For example, consider you have a code that adds an event listener in componentDidMount. The componentDidUpdate method might also contain some logic for setting up the event listeners. Now the cleanup code will be written in componentWillUnmount. See how the logic for the same thing is split between these lifecycle hooks.
React hooks approach this with useEffect.
Now let’s move the logic to a custom hook.
useEffect puts the code that changes together in one place making the code much more readable and easy to understand. You can also write multiple useEffects. The advantage of this is again to separate out the mutually unrelated code.
Wrapper Hell -
If you’re well versed with React you probably know it doesn’t provide a pattern of attaching a reusable code to the component (like “connect” in react-redux). React solves this problem of data sharing by render props and higher-order components patterns. But using this requires restructuring of your components which is hard to follow and, at times, cumbersome. This typically leads to a problem called Wrapper Hell. One can check this by looking at the application in React DevTools. There you can see components wrapped by a number of providers, consumers, HOCs and other abstractions. Because of this React needed a better way of sharing the logic.
The below code is inspired from React Conf 2018 - 90% cleaner react w/ Hooks.
We can check the below example to see how hooks fix this problem.
Hooks provide you with a way to extract a reusable stateful logic from a component without affecting the component hierarchy. This enables it to be tested independently.
Confusing and hard to understand classes
Classes pose more problems than it solves. We’ve known React for a very long time and there’s no denying that it is hard for humans as well as for machines. It confuses both of them. Here’s why it is.
For Humans -
1. There’s a fair amount of boilerplate when defining a class.
2. Beginners and even expert developers find it difficult to bind methods and writing class components.
3. People often couldn’t decide between functional and class components as with time they might need state.
For Machines -
1. In the minified version of a component file, the method names are not minified and the unused methods are not stripped out as it’s not possible to tell how all the methods fit together.
2. Classes make it difficult for React to implement hot loading reliably.
3. Classes encourage patterns that make it difficult for the compiler to optimize.
Due to the above problems classes can be a large barrier in learning React. In order to keep the React relevant, the community has been experimenting with component folding and Prepack but the classes make optimizations fall back to the slower path. Hence the community wanted to present an API that makes it more likely for code to stay on the optimizable path.
React components have always been closer to functions. And since Hooks introduced stateful logic into functional components, it lets you use more of React’s features without classes. Hooks embrace functions without compromising the practical spirit of React. Hooks don’t require you to learn complex functional and reactive programming techniques.
React Hooks got me excited and I am learning new things every day. Hooks are a way to write far less code for the same use-case. Also, Hooks do not ask the developers who are already busy with shipping, to rewrite everything. You can redo small components with hooks and slowly move to the complex components later.
The thinking process in hooks is meant to be gradual. I hope this blog makes you want to get your hands dirty with hooks. Do share your thoughts and experiences with hooks. Finally, I would strongly recommend the official documentation which has great content.
Recommended Reading: React Today and Tomorrow and 90% cleaner React with Hook