It is still commonly suggested among developers that Redux is the best solution for state management in 2020. At this point though, I encourage people to stop jumping to Redux as the first makeshift solution to a perceived state management issue in their React apps. There are now many viable alternatives to using Redux the library: namely, any combination of new React Hooks, clever prop management, and React Context!

The Redux Problem (some background)

In the early days of React, dealing with global state management quickly rose to the fore as the pressing problem that needed a killer solution. It seemed that every week there was a new state management library coming out to solve this problem. Eventually, the community started to settle on Redux and its companion app React-Redux. Why was it successful?

  • For a while, this was a godsend. It enforced a boilerplate usage pattern for organizing global state and brought some order to what could quickly become a chaotic app with makeshift local state management or novel attempts at tackling the shared state issue one’s self.

  • It was also helpful as it forced React developers, a lot of whom were junior developers and just getting into software, to organize their app into repeatable, standardized patterns that were enforced by the API of the library (action, reducer, provider).

  • Last but certainly not least, it facilitated the rise of the very awesome tools such as redux-devtools.

But some issues quickly became apparent

  • An excessive amount of boilerplate is required both to set up and to make any changes to your app. This might seem managable on its own, but when you consider that there is already a lot required to set up a React app (webpack setup, choice of styling solution, SSR, how to deploy). A lof of these problems have become more trivial now but at the time they were not.

  • Gave rise to the temptation to toss everything into global state.

  • The advantage of forcing developers into Redux’s patterns turned out to be a Faustian bargain in many cases: it tricked them into believing that they were engaging in software architecture rather than just implementing a library’s API. This provided a false sense of security in many cases.

  • Led to the rise of React/Redux developers, aka those who had started using Redux before they understood how React works fully. Compound this with the fact that many developers learn JavaScript through React, and you see why this could be an issue.

  • Went hand in hand with the rise of patterns that synergized with it in obfuscating logic (looking at you, HOCs ;)).

Note that these issues compound on one another, meaning that the pain points are more than the sum of these parts.

Again, Redux was quite helpful for a time. But quickly the drawbacks began to outweigh the benefits. We must firstly discourage a premature “jump to Redux”, question whether there actually is a state management problem in most React apps, and lastly do a better job of propogating the myriad of other solutions that exist in the case of a state management problem.

In general, we should be encouraging creativity and innovative solutions as opposed to making developers conform to a one-size-fits-all approach to front-end architecture.

Below are a few suggestions.

Solutions

1. Dont use any “state management solution”

There are ways to avoid using any state management solution

function Page(props) {
const user = props.user;
const userLink = (
    <Link href={user.permalink}>
        <Avatar user={user} size={props.avatarSize} />
    </Link>
);
return <PageLayout userLink={userLink} />;
}

    // Now, we have:
    <Page user={user} avatarSize={avatarSize} />
    // ... which renders ...
    <PageLayout userLink={...} />
    // ... which renders ...
    <NavigationBar userLink={...} />
    // ... which renders ...
    {props.userLink}

(example taken from React docs)

Instead of passing the user info and avatar size directly, we put that info in a userLink variable that also contains the JSX that uses that information and pass that down instead.

It’s worth poking through some of the FAQs in the Redux docs to understand what it’s even doing (frankly, I’m convinced some people don’t even take this step). Caution though that some of the information is outdated.

Dan Abramov has said: “Don’t use Redux until you have problems with vanilla React.” One thing that’s true now that wasn’t then was that what you can do with vanilla React has greatly expanded to include some of what was only possible with Redux or a similar solution.

It’s worth noting that there are also solutions such as local storage as a place to put some state (I use localforage). The added benefit is that this will persist state client-side (though you have to make sure then that they remain in sync with your local state – this is a lot easier with hooks however).

2. Use new solutions such as xState that provide more benefits for a fraction of the overhead

xState is great because it provides a lot of the benefits of Redux (and more) without the boilerplate – if you feel inclined to go through the trouble of understanding the paradigm.

If you’re using GraphQL there’s really no reason to use Redux. Use a library like React Apollo

3. Use React Context

If you’re inclined to stick to “vanilla React,” you can opt for React Context. At its simplest, you create Provider components with their own local state, hook that into the topmost level that you want to state to be shared. A key advantage here is that you no longer need to toss everything into global state. You have finer granular control over these things.

I’ve written about this before, pre-hooks. As a fun challenge, you could change those Provider components to fully use Hooks.

Final Thoughts

I think that once someone has gained at least a passing familiarity with JavaScript, React, and possibly Redux they should take a litle pause. Read up on some design patterns.