DEV Community

loading...

Why I detest React Hooks

allentv profile image Allen T.V> ・3 min read

React Hooks has been the new hotness ever since it was introduced. I have heard many people discuss about how hooks help them write less code with the same functionality and how it is more performant since everything is now functions. There has also been many articles published online touting, we should ditch classes for functions altogether as less lines of code (LOC) is always better.

What gets me, is how folks think brevity is always better and trying to be clever with their code is somehow the best way to write code. I disagree on both fronts.

Brevity should not be at the expense of clarity as code is written for humans, not machines. Any code you write today will be encountered by you or someone else in your team again in the next 6 months. Being able to still understand the context behind that block of code and make changes confidently, is what well-written code is all about.

I always prefer to be explicit rather than implicit. And React Hooks seems to me like a clever hack. Having converted multiple class based React components to functional components using Hooks, I feel like the function is bloated and violates Single Responsibility Principle (SRP). The hook related code seems to be floating around in the function definition trying to separate the main section of how the component will be rendered, from the function signature.

Compare this to a class based React component where every section is clearly separated into functions that are named after what they represent in the React lifecycle or what action they perform for event handlers. Compare this to the useEffect hook which is trying to consolidate mount, update and unmount processes into one. No UI engineer would be confused when they implement lifecycle methods in a class but would certainly be stumped in the beginning when they see the code within useEffect being invoked 3 times when they first implement this hook.

Also, trying to adopt the Redux patterns within React seems like moving from being a library to a framework. React is a very good UI library and gives the freedom to use whatever works in other areas. Trying to push towards the redux pattern of using reducers and dispatchers, is a bad move in my books. Not sure if that is because the creator of Redux is now part of the React team. This reminds me of the example of how the React team was pushing for using mixins in the beginning even when a lot of folks had been burnt using it in either other languages or in Javascript. The React team has now denounced the use of mixins.

I hope React will stay as an excellent UI library that is a go-to standard for high-performance UIs and stop trying to be framework. I would love to see more investment in tooling, especially create-react-app and make it more easier to build UIs by standardizing some of conflicting issues that developers have when they start React projects. This is an aspect that I like about the Go programming language where they have published an article about writing Idiomatic Go code to make sure folks follow the same conventions. The tools that Go has take out most of the friction that teams usually have, making any open-source Go code look very much the same.

I look forward to seeing more improvements in the library that lets developers focus more on implementing business features as fast as possible and reduce friction in writing tests by generating test code for most common scenarios like clicking a button, shallow render, etc

Discussion (1)

pic
Editor guide
Collapse
chrispardy profile image
chris-pardy

This pretty well miss states a lot of things about both React and React hook so let me see if I can correct them.

1) Hooks are better because they're faster/less code etc.
Actually the reason the React team built hooks is to provide a way to encapsulated and share behavior. Traditionally that was done with Render Props or Higher Order Components, those both have problems of composability and adding unnessesary levels to the tree, hooks are a better solution.
Along the same lines while the hooks that are included with React are fine the power comes from leveraging them to build bigger functionality and encapsulate that in a hook. Most of the big React libraries have hooks and using them tends to make your code more readable even if it is longer.

2) Introducing Redux concepts.
There is a "useReducer" hook but firstly the reducer isn't a "Redux" concept (see Array.reduce if you want another example), secondly the inclusion of the hook isn't about pushing in Redux patterns it's more that the React team packaged a hook that they found helpful on complex state management. There are objective reasons why the pattern of actions and reducers is good at complex state management, those are no less true when the state is in a component or a Redux store... But let's say you prefer a different paradigm for managing the state in your component. That's fine the building blocks of useState, useRef, and useEffect are there for you.

3) useEffect is a dumb replacement for lifecycle hooks.
useEffect is where the code you previously had in lifecycle hooks goes now (probably) but it isn't a replacement of lifecycle hooks. If you really care about when your component was mounted you should use the Component class still (they're not getting rid of it) however more likely you were using that lifecycle method to dispatch some asynchronous work. Moving those side effects of rendering into a useEffect hook has 2 benefits. Firstly you couple the create and clean up code together rather than needing to split it between 2 methods, that reduces errors, but also means that you can avoid setting class properties to share state between the methods. Secondly it avoids needing to ensure your code is called from all the potential lifecycle methods that should be triggering it (componentDidMount, componentWillRecieveProps, etc)

The important thing to remember about useEffect though is that it's not trying to be those lifecycle methods. Instead it's a way to tell React "after this component renders, at some point in the future do this." That is far more useful when you're building reusable behaviors than life cycle hooks.
There has also always been a bit of a mismatch between lifecycle methods and React's notion of declarative rendering. Conceptually React has always had the notion that you declare the result of the render and it takes care of the transit. In that world traditional UI framework style lifecycle hooks don't really make sense.