loading...
Cover image for Why React projects still use Redux

Why React projects still use Redux

alexandrudanpop profile image Alexandru-Dan Pop Originally published at blog.alexandrudanpop.dev Updated on ・4 min read

There has been a lot of talk lately of why Redux is not a good option anymore for state management, and why we should use hooks & the React Context API.

As a Redux user, I want to settle the war between Context API & Redux. So let the battle start! ⚔️

Why Redux

Redux got popular for a few reasons:

  • easy to test
  • unidirectional data flow makes it deterministic
  • state is read-only
  • changes are made with pure functions
  • huge ecosystem

redux unidirectional data flow

The problem Redux wanted to solve is predictable state updates. Knowing where and why the state changes and having a "single source of truth" can be an advantage.

I personally think the biggest advantage is testability.

Big apps are constructed on top of lots of tests. 🤓

When applications grow past a certain size, it is pretty obvious no engineer will know exactly what all modules & tiny pieces do.

That's where tests come into place. Tests are the foundation of good software. And Redux code is very easy to test. 

Redux proved to be battle-tested in big React apps. Those apps will be around for a long time and continue to use it. Almost half of React apps use Redux (according to polls and dev surveys) - so you can probably figure out why it's so popular & unpopular at the same time.

The Redux ecosystem

Redux has a large ecosystem of tools and nice things that can help developers do other things than state management. This is a shortlist, for a more extensive one look here.

Debugging

Side effects

  • redux thunk - for async state handling
  • redux saga - awesome for complex async flows, based on ES6 generators
  • redux observable -RxJS-based middleware for Redux
  • redux persist - pretty much as the name states - persists the stores so you don't need to load everything again next time the user will refresh the app - making it an offline-first app

Integrations

And many, many others....

What to consider if using Redux

Beware of anti-patterns:

🐛 making global state out of state that should have been local

For example, making form data global - that's just silly. The form data has no value after it is submitted to the server.

🐛 server state - think if what you are storing is just server state instead of global application state, and in those cases consider solutions as react-query or swr. Those tools have things like Auto Caching + Refetching built-in.

🐛 State duplication - this is a general state management problem. You should avoid duplicating state if possible and instead derive it where needed.

🐛 Doing state updates outside the reducer
Don't do this:

const initialState = {
  complexObjectArray: []
}

const badPracticeReducer = (state = initialState, action) => {
  switch(action.type) {
    case "UPDATE": return {...state, ...action.payload}

    default: return state;
  }
}

const nextState = badPracticeReducer(initialState, {
  type: "UPDATE",
  payload: someArray.map(createComplexObject)
})

Learn best practices

An exhaustive list of Redux best practices and things to avoid can be found here - compiled by the Redux maintainers.

Should you learn Redux in 2020?

Yes - if you want a React job it's a 50-50 chance that the company you go to uses Redux for its product.

But not just because of that - the concepts that Redux became popular for - unidirectional data flow, pure functions, immutable state updates are still worth learning and will make you a better software engineer. 🌟

What about Context API?

While I was also advocating for the Context API for new applications, I am not doing it because I don't like Redux or I don't acknowledge the benefits of using Redux.

I am simply advocating for the solution that will have less complexity for new developers. Using Context API is easier than Redux because it will always go together with hooks that you already know like useState or useReducer.

Redux adds an extra layer of complexity to our application that we carefully need to weight.

Conclusion

I would say Redux is a good candidate for applications of high complexity. Also when the libraries in the Redux ecosystem make sense (for example - if sagas make it easier to reason about complex async flows).

When working with people newer to the React ecosystem and you don't really need the things from the Redux ecosystem I would go with Context API.

Leave a 🧡 & 🦄 if you like this article, also check out my Twitter where I post more cool content.

👇 Comment below 👇
Are you using Redux or Context API?

Discussion

pic
Editor guide
Collapse
markerikson profile image
Mark Erikson

Hi :) Since I got quoted here, I'd like to add some additional, er, "context" to the discussion :)

The big thing here is that Context and Redux are very different tools that solve different problems, with some overlap.

Context is not a "state management" tool. Its only purpose is to make a single value accessible to a nested tree of React components. It's up to you to decide what that value is, and how it's created. Typically, that's done using data from React component state, ie, useState and useReducer. So, you're actually doing all the "state management" yourself - Context just gives you a way to pass it down the tree.

Redux is a library and a pattern for separating your state update logic from the rest of your app, and making it easy to trace when/where/why/how your state has changed. It also gives your whole app the ability to access any piece of state in any component.

So, yes, you can use both of them to pass data down, but they're not the same thing.

For more details, see my posts Redux - Not Dead Yet! and React, Redux, and Context Behavior

Collapse
alexandrudanpop profile image
Alexandru-Dan Pop Author

I'm so happy to have a Redux maintainer comment here! Thanks for the additional references!

I'm glad somebody really stands out and puts such great resources around Redux and how it should be used.

I'm aware of and agree about the Context camparison - that it's not ok. Context is just a dumb provider of storing data in a React Component that is then passing it to anywhere in a React tree. Now to be fair, Redux is also the kind of library that is letting you do most of the work, and it is just imposing some simple rules.

Probably I did not make this article a lot of justice not stating the many anti-patterns or ugly things that can be created using the Context API - as having the tens or hundreds of context providers in your app :).

Collapse
fkrasnowski profile image
Franciszek Krasnowski

Context API shouldn't be considered as a replacement for Redux. It's an alternative for classic callbacks to parent at most. It's not a state manager. If some dude says that Context will replace Redux, he's living in a fantasy. I can bearly see how to compare those two

Collapse
thiht profile image
Thibaut Rousseau

As of 2020 I keep reading everywhere that Redux should be used anymore, but I fail to find what to replace it with. The closest I found was someone who reimplemented Redux with useContext and useReducer, but to me it just feels like a doing a new worse Redux? (No proper logging, time travel, observables...)

Even Dan Abramov says he hates Redux but never suggests a proper way to replace it... Maybe it's because the global store is now considered a bad thing?

Collapse
zarabotaet profile image
Dima

Give a try to Effector. Its framework agnostic tiny reactive library, wich come with selectors and thunks/sagas out of the box.
After a three year's of redux/mobx and some apollo, effector is just a breath of fresh air for me.🙂🙃

Collapse
alexandrudanpop profile image
Alexandru-Dan Pop Author

Thanks! I'll check it out when I get some time!

Collapse
alexandrudanpop profile image
Alexandru-Dan Pop Author

I think it's nice that the core React team is not suggesting something in particular. If they would have done this, it would have hurt the ecosystem for sure - as it would limit innovations and cool ideas. Redux aside, there are a ton of other very cool state management libraries like MobX, Recoil, Zustand, and many more.

Collapse
andrewbaisden profile image
Andrew Baisden

GraphQL is an option. Now while GraphQL is not a replacement for Redux it does help to reduce the need for using it.

Collapse
alexandrudanpop profile image
Alexandru-Dan Pop Author

If the APIs we are using are providing GraphQL then sure! I would not require an API team to build a GraphQL API only for a frontend application. There needs to be multiple consumers or higher business value for that GraphQL API, otherwise, we cannot justify the added complexity server-side.

Collapse
leob profile image
leob

Great article, some fantastic points.

I've seen (in another article) coding using Redux and code using Context side by side, and I noticed how similar they actually were - the version using Context also used immutability, reducers, actions etcetera ... the amount of boilerplate saved was minor. Coupled with the fact that, as your application gets bigger, you probably want Redux anyway, I wonder why then not choose Redux right away.

On thing that make Redux complex to work with is managing and manipulating state in an immutable way, which gets complex fast. But the funny thing is that you have to do it anyway, also with Context and with useReducer. The code to manage state immutably can get hairy fast but there are tools/libraries to make this easier.

(one complexity that I feel Redux does have is in its numerous "side effect" management libraries such as Thunks and Sagas, this is adding to the learning curve)

But one thing is absolutely true, you're right that you highlighted this: don't push state into Redux which you can just as well make component-local! I think that's where the biggest pitfalls are.

Collapse
markerikson profile image
Mark Erikson

The good news is that our official Redux Toolkit package eliminates all the "boilerplate" around using Redux. It includes utilities to simplify several common Redux use cases, including store setup, defining reducers, immutable update logic, and even creating entire "slices" of state at once It also sets up the thunk middleware by default, catches accidental mutations, and more.

I just published a brand-new "Redux Essentials" core docs tutorial, which beginners "how to use Redux, the right way", using our latest recommended tools and practices like RTK and the React-Redux hooks API. I'd encourage you to check it out:

redux.js.org/tutorials/essentials/...

Collapse
leob profile image
leob

That's brilliant, just incredible, I wasn't aware of these tools and documentation.

Right, I see that immer is included, Redux Thunks is included by default, there are standardized ways of creating the store, actions, reducers ...

This makes everything so much simpler, in large part because it's opinionated, which cuts out huge amounts of discussions, confusion, and "choice fatigue". I say it's about time ... discussion, flexibility and "choices" are nice, but productivity and speed are nicer!

Redux has really matured, so I know what I'll choose for my next project.

Thread Thread
markerikson profile image
Collapse
arnaudcortisse profile image
Arnaud Cortisse

That's a nice move!

Collapse
areljannc profile image
AJ Clemente

Many React devs I've met would choose Context API as the default way to manage global state. Little did they know is that without setting Context API properly, it could affect the entire application's performance.

I came across a problem where Context API would re-render every child components that it wrapped. Even memoizing the child components would still cause them to re-render. This was a big no-no for our application since it is data-heavy and will keep on growing in the future.

With Redux, it allows my team and I to debug the application easily, separate the UI layer away from the data, and be able to understand what is going with the application at all times. It is the tooling and mindset of Redux that many developers do not understand why it is such a great library. They focus too much on the boilerplate code, but in reality, it's that boilerplate code that makes maintaining the application a breeze.

Sure, not everyone needs Redux for a blog page. But when you are dealing with an application that will grow and be used by many users, you need a convention defined for you and your team to follow. When you can manage and understand the state, the actions and the UI separately in your application, only then will you appreciate Redux's beauty.

Collapse
wicked7000 profile image
Wicked

I think it comes down to size of the application I've mentioned this on another thread/post before. Your post even touches on it to some extent but if you need a highly testable code base using state/Context can make it much harder. This is because you have to essentially test the component and the state at the same time. With redux you can do these two things mostly independently (you could argue that you still need tests on how your component reacts to certain state updates and so forth).

I also feel like redux 'handles' global state in a much more maintable way for larger applications. However this is pretty much entirely a preference I don't think it's impossible to use Context API/state I think you might just have to be a bit more delligent with how you design your application.

Prior to my most recent project I was using a mix of the Context API and normal react state. However I ran into the problems of testing that I mentioned above. However that's just my two cents I'd be curious to see how others feel!

TL;DR: I feel there is a place for both it depends on the size and testing requirements of a project

Collapse
alexandrudanpop profile image
Alexandru-Dan Pop Author

Nicely said. With Redux we can have independent tests for 3 parts:

  • the components
  • the reducer
  • the sagas
Collapse
wicked7000 profile image
Wicked

Yeah my structure is usually that of:

  • Basic action creator functions (non-thunk)
  • Thunks
  • Reducer
  • Component

I haven't actually got around to trying react-saga and am just using react thunk. But I should get around to trying that out too

Collapse
annietaylorchen profile image
Annie Taylor Chen

I can imagine the difficulty and frustration of understanding redux for beginners, especially if they don't have CS background to back up with many concepts (software architecture, best practice, data flow...). However you're very right on saying that people should consider it, as there is 50% chance that they will meet this at the job. Many apps aren't built today and they have grown big, and it costs the company a lot of money to rewrite or convert it to newer version, not to mention, from a business perspective there is no incentive to do so if the purpose is just to make it easier to developers!

This is the same as Svelte vs. React, no matter how amazing I personally think Svelte is, the job perspective is much lower than React at the moment. So I would learn React first, try to get a job, and have fun with Svelte in my spare time. Until I become a senior who gets to decide what to use, I guess have NO SAY on what to use at all. I just have to follow whatever they prefer, right? :)

Collapse
alexandrudanpop profile image
Alexandru-Dan Pop Author

Hi Annie, as a Svelte enthusiast I know what you say. I wonder if there are big apps out there build with Svelte. There is also this issue here: github.com/sveltejs/svelte/issues/... .

Collapse
annietaylorchen profile image
Annie Taylor Chen

Yeah within the community we're discussing about showcases. It seems there are some relatively big apps, but they're not widely known. The thing is, only more people are using this, there can be more contribution for bug fix or extra libraries. I see in the report the interest to learn Svelte is quite high, so it's a good sign. :)

Thread Thread
alexandrudanpop profile image
Alexandru-Dan Pop Author

Haing some showcases would surely bump those numbers even more over the years, as technical decision makers look for technologies that are proven in the industry most of the time :)

Collapse
killianfrappartdev profile image
Killian Frappart

I did try both and as a beginner I prefer to go with Context API because it is so easy to get started with and there is no external package to install but after reading this post I understand why Redux might be the best choice for bigger project.
I'm now considering diving in Redux deeper to get more job opportunities later!

Collapse
alexandrudanpop profile image
Alexandru-Dan Pop Author

Please consider using learning materials from the official Redux website and Mark's blog.

A lot of old Redux videos and learning materials might not follow the latest best practices. Good luck!

Collapse
killianfrappartdev profile image
Killian Frappart

Will do, thank you!

Collapse
pengeszikra profile image
Peter Vivo

After 3 years redux coding, I turn to usie only useReducer + props without Context, that is the most simple solution. If I faced with complex problem, then change useReducer with useSagaReducer, without use any global state.

// simple combine reducer
export const combineReducers = reducers => (state, action) => 
  Object.entries(reducers).reduce(
    ( prevState, [key, reducer]) => {
        const subState = reducer(prevState[key], action);
        return prevState[key] === subState 
          ? prevState 
          : {...prevState, [key]:subState}
        ;
      } 
    , state
  );

so i think good to know about redux, redux-saga and choose lightest state management for your app - depend complexity.

Collapse
alexandrudanpop profile image
Alexandru-Dan Pop Author

I had no idea of the useSagaReducer hook, pretty cool!

Collapse
stereoplegic profile image
Mike Bybee

Context (or some small library based on it like Constate), Zustand, or other solutions (or combinations thereof), and now definitely keeping an eye on Recoil.

It's also worth noting that RXDB (albeit with a lot of dependency bloat), can handle not only persistence and sync, but all of your app's state management (even if its creator said it's not a replacement for Redux in an issue comment a long time ago), if you're smart about your use of storage and in-memory together. There same is true of Firebase, AppSync, Apollo, etc.

While I've avoided Redux in my own projects for over a year now, and would personally reach for easy-peasy if I did feel like I needed Redux (I never want to look at Redux boilerplate PLUS Saga boilerplate again, just to do async at that), it's still important to know if you're looking for work (there's a good chance it'll be your employer's state management of choice).

And despite my gripes about it, Redux still does it's job and does it well (except async, that's ridiculous) in an incredibly small amount of code - it may seem like bloat compared to just context or smaller libraries mostly based on it, but it's really very small for what it does and the extensibility it offers (the boilerplate, on the other hand, definitely adds up).

Collapse
markerikson profile image
Mark Erikson

As I just linked above, check out our official Redux Toolkit package if you haven't yet seen it.

Collapse
stereoplegic profile image
Mike Bybee

Redux Toolkit is good. I should have mentioned that along with easy-peasy.

Collapse
perpetualwar profile image
Collapse
dbroadhurst profile image
David Broadhurst

Redux toolkit is a game-changer. If you want a clear separation of global state and presentation then it can be easily and cleanly achieved with the Redux toolkit.

Collapse
hinasoftwareengineer profile image
Hina-softwareEngineer

Hey, Alexandru-Dan-Pop, I had an interview last week in which the interviewer asked about redux 3 principles. Can you please tell me those three principles?. As I used redux in only one project but don't know the principles of redux.

Collapse
alexandrudanpop profile image
Alexandru-Dan Pop Author

Single source of truth, state is read-only, changes made with pure functions.
redux.js.org/introduction/three-pr...

Collapse
hinasoftwareengineer profile image
Hina-softwareEngineer

Thank you so much. Now, I got it.😀😀 This link helped me a lot.

Collapse
mzzfederico profile image
Federico Muzzo

Using Contexts and useReducer already feels like Redux lite. And since I feel like states should be as simple and as local as possible, that's a big win. It really makes you think before you end up binding multiple components together. Since actions and reducers are basically the same language, you can install Redux later once you actually grow out of the initial scope. You can start testing early.

Collapse
alexandrudanpop profile image
Alexandru-Dan Pop Author

Yep, useReducer can also be used for complex local state. When that state needs to be shared it can be lifted in a Context or in Redux.

Collapse
urielbitton profile image
Uriel Bitton

Context API. I see the trend going towards Context lately so i'm putting more effort in going that way than staying with Redux which may dissappear in a year.

Collapse
wobsoriano profile image
Robert

"may disappear in a year"

That's not happening

Collapse
markerikson profile image
Mark Erikson

Definitely not happening any time soon :)

Collapse
urielbitton profile image
Uriel Bitton

Maybe not but context api might do the same thing to redux that react did to jquery.

Thread Thread
kornfleks profile image
Alexandre Nicolas

It will not, as mentioned in the top comment, context API has not the same purpose as Redux.
If you doesn't use middleware, you surely don't really need to use Redux.

Collapse
alexandrudanpop profile image
Alexandru-Dan Pop Author

Context API + useReducer hooks would be good enough for many situations:

  • easier to set up
  • no need to understand any extra libraries
  • no extra libs to clutter the bundle size
Collapse
mohitk05 profile image
Mohit Karekar

I recently was building a React app in TypeScript and I felt some friction while I was quickly trying to set up a state management flow. Might not be a problem for everyone, but I was trying to quickly prototype something.

Naturally, I started with Redux, but went on to implement state management in Context. I believe the boilerplate set up for both the approaches is very similar, just the very big plus for me while using Context is that I get to see what exactly is happening, i.e. there is no behind the scenes.

Setting up a useReducer at the root of my app and then providing it with Context is a very simple way to get state management running. Down the tree, you use useContext to pull dispatch and the state. Once this initial setup is done, you can use it normally as Redux.

Collapse
tanvesh01 profile image
Tanvesh sarve

Thanks for this Alexandru! I love redux but whenever I post anything about, I get a lot of criticism which I really don't care about. :)

Collapse
alexandrudanpop profile image
Alexandru-Dan Pop Author

Glad you liked it!
I guess people got scared or sick of Redux for wrong reasons. Maybe they have seen really bad React / Redux apps that made them think it's because of Redux. It's not, if used correctly it's a very good state manager & makes code easier to test and more maintainable.

Collapse
tilakmaddy profile image
Tilak Madichetti

Redux packages gives us a certain recipe that we can follow and build rather than messing around with different react hook based stuff.

Collapse
andrewbaisden profile image
Andrew Baisden

Redux is not going away anytime soon many companies still expect React developers to at least know a state library like Redux.

Collapse
sharadcodes profile image
Sharad Raj (He/Him)

Software for making that gif ?

Collapse
artydev profile image
artydev

Look at meiosis pattern on Dev to
Regards