Skip to content
December 17, 20184 min read

Are new React APIs replacing Redux? (Part 1)

Disclaimer: this post series is discussing alpha features of React. A lot of this is up in the air and is being actively discussed by the React team and the community. The features, problems, solutions, opinions and decisions that these posts discuss might not be final. This is as a summary of the trade-offs being discovered and discussed. I find these behind the scenes discussions to be interesting and educational. Writing these posts is my way of understanding the topics in more depth. Finally, the content is interleaved with with my personal experience and opinions. I hope you enjoy!

This post was in part prompted by the “Provide more ways to bail out inside Hooks” discussion on React repo. Note, I haven’t actually read the whole thing yet 🤭, those threads get pretty long. Update: I read it all by the time I finished Part 3 in this series.

I saw at least 2 aspects being discused in this thread. One is people attempting to use React’s new Context API and Hooks as a replacement for Redux and comparing the capabilities of both approaches. But are these APIs meant to be a replacement for Redux or are they simply complementary? Second aspect of the thread is a discussion among library implementors to identify any gaps in the new React APIs. I’ll focus on the first aspect in this post and the second aspect in the next post.

Even before this thread, I heard similar statements from several people now:

  • Redux is no longer needed now that React has Suspense
  • React’s new Context API can be used instead of Redux
  • You don’t need Redux in Reason React because it has Redux built in

I disagree slightly and here’s why.

I love the direction React team has been taking. Hooks in particular make your code incredibly expressive, succint and composable. And writing all of your components as functions feels great. Not only do Hooks solve multiple problems in React, such as “Wrapper Hell” or “Huge components”, they’re also an improvement over the previous versions of the equivalent APIs.

For example, useState is a better setState, because you’re not limited to using an object for your state and you get to name your state and setters using more meaningful variable names, and of course, composability.

Similarly, useContext is a better version of the old Context API, since it subscribes to changes no matter how deeply your components are nested.

But does useState, useContext and useReducer remove the need to use Redux? Well, it depends on your application. It’s great to have more powerful and cleaner primitives in React. These primitives can be very useful when starting out, and they’re also great building blocks for more complex, use case specific APIs.

And that’s the thing — in my opinion React has excelled in it’s ability to focus on the core set of primitives and let the communities build around their own use cases. I’m confident the React team will resist adding too much API surface area.

If your application benefits from Redux, I’d argue it’s not the best idea to migrate away from it in hopes that you can just use React’s new features instead. Redux does quite a bit under the hood to create an expressive API and good performance. If you swap Redux with your hand rolled Context and Hooks based store, you might run into sveral pitfalls (More on that in Part 2 of this series).

Implementation details aside, there’s a larger question at play here of whether Redux style global stores are a good approach to modeling applications. Local state as encouraged by the useReducer hook, React Suspense or Reason React seems to be a preferred approach by the React team. That is discussed more in Part 3 of the series.

React Hooks will allow us to create nicer APIs for all of the existing state and data management solutions. For example, if you’re using react-refetch to bind your components to REST APIs, instead of having to use a Higher Order Component to connect, in the future you might instead do something like:

function MyComponent({ id }) {
  const user = useResource(`/api/user/${id}`)

If you’re using GraphQL, perhaps something similar with Apollo:

function MyComponent({ id }) {
  const user = useQuery(`query { user(id: $id) }`, { id })

And none of this means you can’t or shouldn’t be using Redux. In fact, Hooks will make using such stores really nice in the future:

function MyComponent({ id }) {
  const user = useStore(state => state.users[id])
  const dispatch = useDispatch()

Having said that, it’s likely that this new set of APIs – Hooks, Suspense might create entirely new patterns, approaches and libraries. But they will also make the existing tools better, because these APIs are a truer expression of what React is really all about.

Part 2 of this post goes into more technical details in exploring edge cases, limitations and open questions around usage of Hooks that I, as a library implementor, came across.

And finally, if you’re already using React 16.7.0-alpha and would like to use a global store via Hooks, checkout tiny-atom, a store similar to Redux, but with a more compact API.