top | item 22822831

(no title)

thekemkid | 5 years ago

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.

discuss

order

acemarke|5 years ago

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].

[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...

Scarblac|5 years ago

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).

runawaybottle|5 years ago

I’ve read articles about how the Ducks pattern in practice also become untenable.

runawaybottle|5 years ago

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.

ratww|5 years ago

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.

acemarke|5 years ago

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.

[0] https://blog.isquaredsoftware.com/2019/10/redux-starter-kit-...

[1] https://blog.isquaredsoftware.com/2017/05/idiomatic-redux-ta...