This blog post assumes you have a decent initial understanding of React Hooks. I highly suggest starting with the ReactJS Docs on them first.
As developers start adopting React Hooks within their applications, many will be tempted to start with
useState as their state management
preferences for local component state. However, I would like to try an convince you that
useReducer is a better way
to manage local state.
Lets start of with defining "better" in my premise from above, the definition I will use for this article will be that its:
So lets break down each of these three points.
As with most of this blog post, this is mostly my opinion, however because
useState no longer shallowly merges state updates
like it does within classes, using a reducer function gives you the developer more control over the state merging.
As an example of this expresivity that a reducer gives us, we can
useReducer to implement an undo/redo state management solution 1:
Using this reducer we can keep track of a stack of states that happen in the future and in the past, allowing the user to undo and redo their actions.
This would be fairly difficult to coordinate using
useState, thats not to say that its impossible but the benefit of
is the explicitness of this pattern. Which leads into the second point.
Probably a topic for another blog post, but there is no such thing as a tech-only problem in web development. Frequently, you will be building features with other developers, that have a wide variety of experience different from your own.
This is mostly a more generic topic that permeates through other topics than just React Hooks, but the general take-away with
the benefit of
useState is it builds on the concepts that many developers learned working with Redux
within React applications2. The concept of dispatching an action and having your reducer handle the state updating logic will
allow these developers to more easily grasp this method of state management over
One thing to note in this reasoning, is that even if you are building a project all by yourself, you can consider the future you that comes back to work on the project as another engineer.
If there is one general topic that I have seen the most in discussions on the original Hooks RFC, or the React repo since the 16.8 release,
or even on Twitter its how developers are really confused with how to test Hooks. I think it might take developers a while to
learn how best to test their hooks and components using hooks, however the beauty of the
useReducer hook, is that all your
business logic for updating the state can exist in a separate function that is exported separately from your component.
This separation of the state updating logic and rendering logic, allows you to author tests for the state updating separate from
the component rendering tests. Using our reducer from the above snippet, we can easily test the logic for undoing and redoing actions
simply by calling our
reducer function from with the test using some mocked state, and an action. We don't even need to
import or use react at all within our test!
I don't expect to persuade most developers to only ever
useState, nor do I personally expect to only ever
useReducer hook over
useState, they both have benefits and fallbacks that depend entirely upon their use. However,
I do think that
useReducer when used as a replacement for complex state management happening within an old class based component
or replacing a react-redux setup can be more maintainable.
Have feedback about this post or questions, don't hesitate to reach out on Twitter (@immatthamlin)!