Avoid Redux in your Enterprise-Level Web Applications

Redux is awesome, don’t get me wrong. But it has its pros and cons. I worked with Redux for many years and I also had the chance to try out other state-management libraries. But most of them failed in different areas. Here are a few things you should consider.

“What on earth is Redux I keep hearing about?”

In a nutshell, Redux can be considered as a central store that manages the state of an application built in React, Angular, or other popular frameworks. Each of its components can access the given stored state without requiring sending down property from one component to another.

Here is a summary of Redux’s architecture:

Redux Architecture
  • Reducer: Logic that decides how your data changes exist in pure functions
  • Centralized store: Holds a state object that denotes the state of the entire app

It is a great library to learn though, it will build up your skills and knowledge and teach you about many useful concepts when it comes to software development.

“So why should I avoid it in my next enterprise-level web application?”

Photo by Dmitry Ratushny on Unsplash

If you’re starting out with Redux, it’s probably not a great idea to build a scalable & enterprise-level ready application. This is because you probably don’t have the right skills to build one. Such an application requires a well-thought structure to allow maintainability and scalability.

Photo by Fang-Wei Lin on Unsplash

Most of the tutorials and courses you’ll find online will showcase a simple Redux application. Some of them will teach you how to build a TODO app, which is fine, but not enough to give you the right skills to build the next award-winning or interprise-level web application.

Sure, some paid courses would teach you about handling asynchronous calls for example, but so far I haven’t seen a proper course that teaches you how a senior front-end engineer should build an enterprise-level application (I mean with proper structure, best practices, normalization, handling async requests, testing & TypeScript).

Let’s face it. When adding redux, you have to write a bunch of code. Think about all the types, actions, operations, reducers, and tests you have to write! This, without mentioning all the custom middlewares you have to add and manage. Have you thought about all the loading, success & error states you have to manage in each asynchronous action? Sure, you can wrap that logic in a separate UI reducer and make custom selectors. What about all the components where you have to import useDispatch and useSelector? At a certain point, it becomes really boring, hard to manage, and not fun to code anymore (see next point).

Photo by Ricardo Viana on Unsplash

There are a few common use-cases where things can get messy. I will just name a few.

  • Working with other developers can be a pain point. Some of them might prefer everything in a single file (types, actions, reducers) — ducks pattern. Others might prefer multiple files, even when the “feature” is small and probably doesn’t require 6 files (like actionTypes.js, actions.js, reducers.js , operations.js , selectors.js , index.js ).
  • Although it’s important to separate concerns, sometimes it can be hard to manage interconnected features.
  • Working with async code requires a lot of boilerplate or even the need to use middlewares (ie: redux-thunk, react-redux-promise). Without middlewares, things can get even messier, with action types like.
const FETCH_USERS_REQUEST = “FETCH_USER_REQUEST”;
const FETCH_USERS_SUCCESS = “FETCH_USER_SUCCESS”;
const FETCH_USERS_ERROR = “FETCH_USER_ERROR”;

Imagine you have 50 different action types like these!

Photo by Scott Graham on Unsplash

Ok, this is not about which library you should use to test your react applications, but let’s say you want to test the internals of a component that is connected to the Redux store using Jest/Enzyme. You have to wrap your component with a custom Redux provider and add the appropriate initial values. I find that sometimes it’s not ideal as you might end up with endless errors.

Photo by Chris Barbalis on Unsplash

Have you ever tried to refactor an existing Redux application into Typescript? I just sincerely wish you Good luck! 🤞

No encapsulation. Any component in your application can access the data which can cause security issues.

As state is immutable in redux, the reducer updates the state by returning a new state every time which can cause excessive use of memory.

“What can I use then?”

  • You can use React Hooks to create your own state management custom hooks. There are plenty of tutorials and courses about this.
  • The React Context API could be also an alternative.
  • Have a look at React Query (personal preference), which is a revolution in my opinion. This works for both REST APIs as well as GraphQL.

Fetch, cache and update data in your React and React Native applications all without touching any “global state”.

Instead of writing reducers, caching logic, timers, retry logic, complex async/await scripting (I could keep going…), you literally write a tiny fraction of the code you normally would. You will be surprised at how little code you’re writing or how much code you’re deleting when you use React Query.

  • Another alternative is SWR (more appropriate for JAMSTACK applications).
  • If your backend supports GraphQL, you can also go for Apollo Client.

As always, happy coding! And don’t hesitate to share your thoughts about this article in the comments section 🙌

👨‍✈️ Airline Pilot, 👨🏻‍💻 Software Engineer, 👨🏻‍🎨 Designer, 🎵 Musician & 🏋🏻‍♀️ Fitness Addict

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store