- 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].
[0] https://blog.isquaredsoftware.com/2019/10/redux-starter-kit-...
[1] https://github.com/reduxjs/redux-toolkit/releases/tag/v1.3.0
[2] https://redux.js.org/style-guide/style-guide#structure-files...
[3] https://redux-toolkit.js.org/usage/usage-guide#exporting-and...
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).
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 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.
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.
[0] https://blog.isquaredsoftware.com/2019/10/redux-starter-kit-...
[1] https://blog.isquaredsoftware.com/2017/05/idiomatic-redux-ta...