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
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
- redux socket.io - for using the popular socket.io realtime communication library
- redux react firebase - firebase integration
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}
<span class="nl">default</span><span class="p">:</span> <span class="k">return</span> <span class="nx">state</span><span class="p">;</span>
}
}
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.
Latest comments (57)
Thanks for this wonderful article !
I appreciate the article, but we really need to be cautious about writing "depends on the size of the project or situation" type articles related to Javascript development choices.
In particular, with React, Redux has been a major source of project delays and near failures in my 4 years of React dev experience. Also, arguing over "redux vs mobix vs context" has created thrashing on projects, division in the community and another wave of "javascript fatigue".
Use Redux for legacy applications only! Use Context going forward. ...And spend time focusing on your product, not hemming and hawing over esoteric concerns.
I'd love it if you wanted to dissect my Redux one line replacement hook... useSync
dev.to/chadsteele/redux-one-liner-...
the poll said redux will die in 3years from 2020 so why the need to learn it when you can spend time learning Context API
Thanks Alexandru-Dan for this article. I am not well versed in React (for now) but having created many applications in Angular I can tell you the Redux fatigue is here. Luckily we have good toolkits and best practices but we often end up with a different implementation by developer by team.
The most common question is: Should everything be in Redux? Should every action performed in the application be handled by Redux? Common sense tells me that Redux should only manage (persistent) state, but then come a problem because we end up with a very hybrid solution with some actions (search, filters, authentication) in Redux and some others not (CRUD like actions on an entity).
I still like Redux but it adds a lot of boilerplate and complexities and it is sometimes very hard to teach it in teams of junior or mid-level developers. This is sometimes a point that is overlooked by documentations in the sense that when we manage multiple teams and multiple developers the best solution is often the most universal, opinionated and strict as to avoid too many different implementations that increase technical debt and decrease readability and maintainability.
And it's becoming even more difficult because of SSR and Pre-Rendered Sites as state is not (easily) shared between server and client.
So it's nice to read different opinions on the question of Redux.
Good points!
I think Redux is getting more mature with solutions like Redux Toolkit & RTK Query (that is still alpha but sounds promising).
Angular also has the NGRX store that is a Redux-like implementation for the Angular ecosystem - I think this proves the Redux popularity.
React Query is another popular solution to avoid boilerplate - but this one has a learning curve as well for advanced usage. But it's nice because it will invalidate and re-fetch the cached data.
SSR & pre-rendered sites - haven't used Redux in those scenarios - so I honestly can't make a statement for it. I only used Redux for fully CSR apps.
As a small conclusion, if you spend too much time researching what advantages Redux brings or what cons it has, you might not need it. You will know when you need it in those cases:
Look at meiosis pattern on Dev to
Regards
Redux is not going away anytime soon many companies still expect React developers to at least know a state library like Redux.
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
Maybe it's dying specifically in React applications
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.
so i think good to know about redux, redux-saga and choose lightest state management for your app - depend complexity.
I had no idea of the
useSagaReducer
hook, pretty cool!Amen.