I first wrote it back in 2018, and just updated it yesterday with some additional links and comparisons.
(Actually was considering retitling it after getting some feedback last night, but given that the link just got submitted here, I'll leave it as-is for now.)
A few quick notes:
- If you haven't looked at Redux in a while, please try out our official Redux Toolkit package [0], which is now our recommended approach for writing Redux logic, and the React-Redux hooks API [1]. We're going to be teaching both of those as the default approach for using Redux going forward.
- We have a new "Style Guide" docs page that gives our official guidance on suggested usage patterns [2]
- On that note, I'm working on an ongoing major rewrite of the Redux core docs [3]. My current task is creating a new "Quick Start" tutorial, which will be a "top-down" intro to using Redux to stand alongside the existing "bottom-up" tutorial sequence. The goal of the Quick Start section is to quickly introduce Redux concepts, and show RTK and hooks as the "right way to write Redux code", without going into the details of how it works under the hood, so that folks can get started now and learn the underlying aspects later. I've an early partial WIP draft PR up [4], and hope to finish the first draft in the next few days. Once the Quick Start page is done, I'll be turning my attention to rewriting the main tutorial sequence in order to remove outdated terms, clarify explanations, and teach simpler patterns (like using "ducks" files instead of splitting code across multiple files).
If anyone's got questions on anything I wrote in the article or otherwise Redux-related, ask away!
That was a great article—wish I had read it back in 2018! I'll chime in with some thoughts, as someone who has built several apps using React/Redux.
What's happened with me (and others I've seen) has been discovering Redux, falling in love, and thinking "I'll use it for everything!" There's something about the simplicity of having a single state tree, that is immutable and debuggable that just blows your mind.
Then you start building, and after writing your Xth action/reducer/selector/dispatch/etc, you tire of the boilerplate and the overhead.
So where I've landed is:
1) we use Apollo/GraphQL for data-fetching and caching.
2) we use hooks in general.
3) for deeply nested component communication, we haven't fully settled on whether to use redux or not and kind of mix it up depending on the circumstance
4) we use redux when we need app-wide state and/or debuggability (so everything that's not 1, 2, or 3).
This has worked pretty well for us, though (3) is still a little fuzzy.
Anyway, I do think Redux is awesome, so thanks for maintaining it. But just wanted to chime in that I think a lot of "Redux is dead" sentiment (besides just being article click-bait and sensationalism by publishers) is actually people realizing that they've done the "everything is a nail" thing and retreating a little bit from that.
Yeah, as I tried to make clear in the post, there's many other excellent tools and libraries in the ecosystem, and they _do_ overlap with the kinds of use cases that might have made people pick Redux in the past.
For the record, I've never wanted _everyone_ to use Redux, and I agree with criticisms that Redux has been frequently over-used.
All I want is for folks to look at their use cases, take the time to evaluate tools, and make intelligent decisions about what tools best solve their problems.
Unfortunately, the nature of social media and the development community just doesn't seem to work that way. No one seems to write posts saying "here's a new tool, here's how it compares to existing tools, and here are the tradeoffs involved and the use cases where they might each be relevant". It's always "LOL TOOL X IS DEAD NOW!", even if Tool Y is brand new and has 10 downloads and 2 GH stars while Tool X's daily downloads continue to increase.
Thanks for sharing this, is interesting to hear what other folks are doing in practice!
We were actually thinking of migrating to something similar in terms of data fetching to Apollo/graphql and leaving redux for more app wide state problems.
Could you share any further insights on how you started organising this project? I.e. some pieces in Apollo/graphQL while maintaining a redux core, (presumably that's the core you started with?). Would be really interested.
Also I share your sentiment exactly, redux isn't dead. It's still a really solid approach to state management, and in complex applications I still think it's one of the best options. Thanks and kudos to the maintainers!
I’ve been loving redux toolkit so far, so great job on that! The docs are super good too, so props for wanting to improve them further.
I encourage everyone to try out redux toolkit if you feel like redux is too much boilerplate. It also comes with immer out of the box, so no more crazy spread operators.
Do you, or anyone else in the team or community, have a good resource you would recommend to people complaining about "too much boilerplate" in redux code? It is likely the most common complaint I see, that I understand to come from a place of people not understanding it this a tool best used for scaling and/or already big projects. Whenever I have worked with Redux in a large project, that "boilerplate" is minimal and the benefits obvious.
Yeah, as I talked about in both the original blog post and my parent comment, we've specifically designed Redux Toolkit to eliminate the "incidental complexity" that came along with using Redux [0]:
- Immer makes writing immutable updates easy, because you can write "mutating" logic like `state.todos[5].completed = true`
- `configureStore` sets up a Redux store with good defaults (DevTools extension, thunks, mutation checking) in a single line of code and has easier-to-read options if you do need to tweak the config
- `createSlice` eliminates the need to write any action creators or action types by hand
- Our new `createAsyncThunk` and `createEntityAdapter` APIs (new in v1.3.0 [1]) simplify the common use cases of dispatching actions as part of data fetching and managing normalized data in your state
Also, RTK is written in TypeScript, and designed to infer as much as possible. For example, if you declare the type of the action payload in a `createSlice` reducer, the generated action creator has its payload argument typed automatically to match.
Meanwhile, the React-Redux hooks API generally requires less code than `connect` does, and is easier to use with TypeScript as well.
Finally, we're now encouraging folks to use the "ducks" pattern for single-file Redux logic [2], which cuts down the number of files you might have to work on for a given feature, and using `createSlice` basically gives you ducks files for free [3].
I think that complaint usually comes from people who try to put everything related to state in Redux, and not just the parts of it that need to be.
Also the 'reducks' pattern of splitting the Redux state into separate files, each containing a reducer and the related actions and selectors helps keep things simple to understand (although I guess it is a bit more overhead, actually).
What are the obvious benefits other than fundamentally dumping shared data into a global singleton?
How do you handle testing of connected components? There’s tons of pain points. I’m on a pretty large Redux project too, and every day I wish I could just simplify the whole app (as we scale) by removing Redux.
I don't know if I agree... I've used "traditional" Redux in very large projects and the boilerplate far from minimal, and it grows in the same scale the app grows. And it's in the parts that grow more, which is app code: action types and action creators are very un-DRY and repetitive. Switch statements are way noisier syntatically compared to other solutions such as classes or objects (used in VueX and RTK createSlice). Etc.
I think it speaks volumes when the Redux maintainers are going into a direction that uses less boilerplate, like Redux Toolkit.
Honestly, there's nothing wrong with boilerplate, but I guess it's time to admit that some people love it and others hate it.
I think it's important to distinguish between the "inherent" complexity" and "incidental" complexity in using Redux [0].
Dispatching actions and writing reducers is _inherent_ complexity. It's part of Redux's design, and is a deliberate level of indirection.
Having to write nested spread operators to perform immutable updates, switch statements in reducers, and `const ADD_TODO = "ADD_TODO"` is _incidental_ complexity. Nothing about Redux's core design _requires_ you to write the code that way. There's valid reasons why those patterns exist [1], but writing a reducer with a switch statement vs a lookup table doesn't change how the Redux data flow behaves.
My goal is to eliminate the incidental complexity, because it's not necessary and does present a barrier to people learning and using Redux.
I first wrote it back in 2018, and just updated it yesterday with some additional links and comparisons.
(Actually was considering retitling it after getting some feedback last night, but given that the link just got submitted here, I'll leave it as-is for now.)
A few quick notes:
- If you haven't looked at Redux in a while, please try out our official Redux Toolkit package [0], which is now our recommended approach for writing Redux logic, and the React-Redux hooks API [1]. We're going to be teaching both of those as the default approach for using Redux going forward.
- We have a new "Style Guide" docs page that gives our official guidance on suggested usage patterns [2]
- On that note, I'm working on an ongoing major rewrite of the Redux core docs [3]. My current task is creating a new "Quick Start" tutorial, which will be a "top-down" intro to using Redux to stand alongside the existing "bottom-up" tutorial sequence. The goal of the Quick Start section is to quickly introduce Redux concepts, and show RTK and hooks as the "right way to write Redux code", without going into the details of how it works under the hood, so that folks can get started now and learn the underlying aspects later. I've an early partial WIP draft PR up [4], and hope to finish the first draft in the next few days. Once the Quick Start page is done, I'll be turning my attention to rewriting the main tutorial sequence in order to remove outdated terms, clarify explanations, and teach simpler patterns (like using "ducks" files instead of splitting code across multiple files).
If anyone's got questions on anything I wrote in the article or otherwise Redux-related, ask away!
[0] https://redux-toolkit.js.org
[1] https://react-redux.js.org/api/hooks
[2] https://redux.js.org/style-guide/style-guide
[3] https://github.com/reduxjs/redux/issues/3592
[4] https://github.com/reduxjs/redux/pull/3740