My FeedDiscussionsHeadless CMS
New
Sign in
Log inSign up
Learn more about Hashnode Headless CMSHashnode Headless CMS
Collaborate seamlessly with Hashnode Headless CMS for Enterprise.
Upgrade ✨Learn more

Why can't Context API or Hooks API replace Redux?

Vijay Thirugnanam's photo
Vijay Thirugnanam
·Nov 23, 2018

This week, I had a lot of time to go over the new Hooks API. One thing that struck me as really good in the Hooks API was the useReducer hook. I thought the React team has found an in-built solution to manage global state. And I was all over it. I started writing a blogpost saying that we don't need Redux as we have the useReducer hook .

Apparently, useReducer hook was not going to solve the global state problem. I was under the impression that if I call the useReducer hook twice, I will get the same underlying reducer state. That is not the way how useReducer works. Each call to useReducer hook even though we refer to the same reducer function maintains its own state.

Instead of admitting defeat, I decided to build a Redux clone without middleware support just to see how it goes with the new API. I saw the useContext hook and figured out a way to put the reducer state and the dispatch in a context. Then in downstream components, I can call the useContext hook to get the global state and the dispatch. Before testing the solution, I wrote another blog post and this time published a NPM package something like a redux clone.

The story was well received by the community. Oddly, it was a bit away from what Facebook recommended to do with useReducer. First putting the global state in Context meant all components which used useContext re-renders. That is awfully wrong. So, React core team recommends to put the reducer dispatch in the Context. And pass the reducer state via props. Unfortunately, there was no way to share reducer state across container components.

This prompted me to see value in Redux. So, Redux is the proven nice way of having global state in a store. Ability to dispatch an action to all reducers in the store. And cause global state updates to be passed on to all connect HOC which re-renders the component if the relevant state changes.

I wrote another blog post - Why we need Redux and HOCs ?

In the new blog post, I explain why putting global state in Context requires something similar to a connect HOC. And then present an alternate solution - useStore hook which subscribes to state changes on a global store object.

This is what I learned this week about the new Hooks API:

  1. useState internally uses useReducer.
  2. Calling useReducer twice with the same reducer function does not return back the same state.
  3. There is no built-in way for reducer state to be shared across container components. Hence the need for Redux or a global state by combining all reducers.
  4. Calling useContext hook causes re-render whenever the context changes. And there was no way to cancel the re-render or update.
  5. The solution to cancel an update or re-render from within a functional component using hooks is to use our good old HOC pattern.

Still Hooks is in Alpha. So, I will reserve judgements on it. But overall, it does not solve all the problems developers have. Some of the problems that are not solved.

  1. Avoid updates when context changes in useContext hook.
  2. Using the useReducer hook multiple times with the same reducer function to get the same reducer state.
  3. Equivalent of a Pure Component without creating a HOC or container component. No cancel update hook.

Overall lot of learning this week. I was hoping the Hooks API and Context API will replace the use of Redux. But sorry, not yet. Not yet with Hooks Alpha at-least.