React Class Components vs Functional Components with Hooks: A Never Ending Story
A lot of developer teams choose to use React class components instead of functional components with hooks for the wrong reason. To me, it’s surprising to see this discussion over and over again. React released hooks over two years ago, it’s a proven approach and many developers are still not sure if it’s a good idea to use them or not. I feel like this topic is a never ending story. I would like to talk more about this topic more and why developers are struggling to use React hooks.
If you tried to use hooks, but you were struggling using them and your code was buggy, no worries, I was there too. You just need to get over it and you will feel much more comfortable using hooks.
First, let’s start with the basic concept of React hooks.
What are React hooks and what they solve?
Before hooks, functional components were stateless and they were used for simple components. When hooks were released, the main motivation was having functional components with the same capabilities as class components. React docs summarizes the main motivation very well, but let’s talk about this more with some examples.
Reusing stateful logic
React hooks allow you to easily reuse stateful logic between components, which is very powerful in implementation workflow. You can extract stateful logic from a component into a hook function.
Before, we used HOC and wrapper components, which leads to an overcomplicated code base.
Here's something for ya. Lol. pic.twitter.com/ZWWAxMFpbZ
— Grex 🇺🇸 (@GrexQL) September 27, 2018
It takes more time to restructure your application with multiple hierarchies instead of encapsulating shared logic into a hook function.
Efficiency
Class components require you to write more code. You can see some examples and statistics in Amelia Wattenberger’s blog post Thinking in React Hooks. Most of the time you implement different scenarios, but you can be sure you will feel more productive using react hooks.
React libraries support
There are great React libraries such as React Query, Framer Motion, Apollo Client that don’t support class components or it’s complicated to use them in class components. You will see this trend more often in the future and it will be more complicated to use class components.
Why React developers don’t use React hooks
React hooks rely on Javascript closures and this can be sometimes tricky to understand. The most common issue with hooks is that you are not getting the current state in a callback function. Ben Awad made a great video about this issue:
As you can see in the video above, solving this issue is very easy. However, if developers are not experienced with closures, it can be really hard to figure out what’s wrong.
This is the main reason why a lot of developers and developer teams don’t want to use react hooks. If you go over this hooks closures concept, you can happily use hooks and nothing surprises you.
Conclusion
In this blog post I wanted to summarize what are the main benefits of using React hooks. Then you can see why developers don’t want to or give up to use them. Using hooks have more pros than cons so it makes sense to learn and start using them. Unfortunately, a majority of developers and developer teams prefer concepts that are easier to understand and make fear-based choices.
If you understand stale closures in Hooks, you can use them without any issues. If you feel like I am missing something in this blog post, please let me know.
Understanding the basics
React doc’s says there are no plans to remove classes from React. However, there are popular libraries that don’t support class components. In the future, we will some libraries which drop support for class components.
In some cases, refactoring class components to functional components with hooks can be huge amount of work. It doesn’t really make sense to refactor existing project, but it makes sense to start using React hooks.
You can’t use Hooks inside a class component. However, you can use HOC (Higher-Order Components) pattern to use hook logic inside existing class component.