Lots of colleagues have been asking me variations of the same question:
“If we’re using hooks in our project, are we going to even need Redux?”
“Don’t React hooks make Redux obsolete? Can’t I just do all the same things Redux does with hooks?”
A quick Google search will show that people are asking these questions all over the internet.
The fast answer to “Do React hooks replace Redux?” is “not really.”
The more nuanced but polite answer is “Well, that really depends on the kind of project you’re working with.”
The answer that I’m inclined to tell people is “I’m not sure you know what you’re talking about.” There are a few reasons why “Do React hooks replace Redux?” is a fundamentally flawed question. To begin with:
Redux is and has always been optional!
According to Dan Abramov (one of the creators of Redux), you might not need Redux. You don’t need to replace something if you don’t need to use it to begin with.
When people ask if hooks replace Redux, they often seem to believe that their React apps need to be using one or the other. That’s not the case. If you’re writing an app that doesn’t have a lot of state that needs to be stored, or if your component hierarchy is simple enough to avoid excessive prop drilling, then it doesn’t make sense to use a whole state management library. Your state is manageable enough with what React has to offer, with or without hooks.
And even if you do have an enormous application state, or a React component hierarchy that twists and forks like the roots of an ancient tree, you still don’t need to use a state management library. Prop drilling may be bothersome, but plain old React gives you plenty of state management options, and hooks can definitely help you keep your state organized. Redux is a lightweight library, but it’s complicated to set up, adds to your bundle size, and comes with various trade-offs. There are plenty of reasons why you might choose not to use it in your project, and all of those reasons are valid. You don’t always need Redux.
All this being said, there are plenty of reasons to use Redux too. If your project has been using Redux from the beginning, there was probably a good reason for it, whether it has to do with organization (having a predicable, single source of truth for application state can be useful in complex apps), middleware, or Redux’s powerful developer tools and debugging abilities. If you had a reason to use Redux, React hooks aren’t going to invalidate that reason. If you needed Redux before, you probably still need it. This is because
React hooks and Redux aren’t trying to solve the same problems!
Redux is a state management library. Hooks are part of a recent update to React and let you write functional components that do everything you used to need a class component to do.
So why does the ability to write React apps without using classes suddenly make state management libraries obsolete?
According to the docs, React hooks were developed for three main reasons:
- It’s difficult to reuse logic between class components.
- Lifecycle methods often contain a confusing mix of unrelated logic.
- Classes can be difficult for both machines (and humans) to understand.
Notice that none of these motivations directly have anything to do with state management.
That being said, React hooks do give you a few new options for managing application state. Notably, the methods
useContext give you new ways to maintain your state that are arguably better and more organized than the options React gave us before hooks.
But these hooks aren’t anything new or magical, and they don’t make state management libraries obsolete, because the truth is,
React hooks don’t let your React app do anything it couldn’t do before!
That’s right. You can now write functional components that do things you used to need classes to do, but those functional components don’t do anything class components can’t do, aside from arguably having better organization and ability to reuse code. They won’t necessarily make your app better. Hooks are about making the developer experience better.
useReducer are just ways of managing component state, and they work just about the same way
this.setState do in class components. You’ll still need to drill down your props using these methods.
useContext is the one people seem to think puts the nail in the coffin for Redux, since it lets you share application state across components without prop drilling, but this one doesn’t really do anything new either. The context API has been part of React for a while now. The
useContext hook just lets you use context without having to use a
<Consumer> wrapper. And while some developers opt to use context to manage their entire application state, that’s not really what it’s designed for. According to the docs,
Context is designed to share data that can be considered “global” for a tree of React components, such as the current authenticated user, theme, or preferred language.
In other words, things that aren’t expected to updated frequently.
The docs also recommend using context sparingly as “it makes component reuse more difficult”. They also warn developers that it’s easy to trigger unnecessary rerenders with context if the developer isn’t careful.
I’ve seen projects successfully use React context to manage application state. It’s possible. It’s another option. But state management isn’t quite what context was designed to do, while Redux and other state management libraries have been designed with this specific purpose in mind.
Furthermore, React hooks definitely aren’t the death of Redux, because, if you take a peek at the docs for recent updates to React-Redux, you’ll see that
React-Redux has its own hooks, too!
That’s right. React hooks are helping to revitalize the React-Redux library and remove some of its pain points, a far cry from “replacing” it.
I go into more detail about React-Redux hooks in another article, but here’s the main point. Before hooks, you had to define
mapDispatchToProps functions, and wrap your component in the
connect function, to create a higher order component that would pass the dispatch functions and parts of the Redux store you specify in your mapping functions into your connected component as props.
Let’s look at an example for an extremely simple counter app (too simple to even need Redux, really, but this is just meant to be an informative overview.) Imagine we’ve defined a Redux store and
decrement actions creators somewhere else (look at the article I linked above for the full Redux code.)
How annoying. Wouldn’t it be nice if we didn’t have to wrap our component in a higher order component to get it access to the Redux store? Well, that’s where hooks come in. Hooks are all about code reuse and eliminating the need to enter “wrapper hell” via higher order components. Here’s the same component, converted to a function using React-Redux hooks”
Isn’t it beautiful? In short,
useSelector lets you save pieces of your Redux store as variables in your component.
useDispatch is extremely simple. It just gives you a dispatch function you can use to send updates to the Redux store. Best of all, you no longer need to write these ugly mapping functions and wrap your component in the
connect function. Now, everything is nicely contained within your component. It’s much shorter, and therefore more readable and, arguably, better organized. The point is,
There’s no need to frame React hooks and Redux as technologies in competition.
Clearly, these two technologies can wonderfully complement each other. React hooks don’t “replace Redux,” they just give you new and arguably better ways to organize your React apps, and let you write better connected components if you do end up deciding to use Redux to manage your state.
So please, stop asking “Do React hooks replace Redux?”
Instead, start asking yourself “What kind of app am I making? What kind of state management needs do I have? Does Redux make sense, or is it overkill? Do hooks make sense, or should I stick to classes? If I decide to use Redux and React hooks (or MobX and React hooks, or Redux with jQuery and no React — these are all valid options depending on what you’re doing), how can I make these technologies complement each other and work together in harmony?”