Hacker News new | ask | show | jobs
by Couto 842 days ago
React was closer to elm during the times of stateless functions and redux. Since then it's getting further apart from elm.

Redux was kinda of a poor man's elm but it got the right principles. However the JS community hates boilerplate code so, new, more complicated abstractions appeared. Also, it was too easy, with redux, to shoot yourself in the foot.

Since then, with hooks, things are just getting harder and more complicated in my opinion.

2 comments

Redux had some strange "features" that increased boilerplate without bringing anything worthwhile: mapDispatchToProps (I see it is gone since hooks, I could never find any sensible reason to use it the way authors wanted), global reducer, serializable state, serializable actions.

I once counted how many things you had to do to add new button with new action (it was when class components were still acceptable) - you had to change 4 files in 7 different places. This was completely insane for me. After little fighting with Redux (so I could pass nonserializable actions) I went down to 2 changes in 2 files (to dispatch action and to reduce it).

Redux is better now but I do not think its principles were that good.

Hi, I'm a Redux maintainer. A few notes here:

- It was never necessary to write `mapDispatchToProps` as a function. `connect` always supported an "object shorthand", where you passed in an object full of action creators, and we recommended that as the default: https://react-redux.js.org/using-react-redux/connect-mapdisp... . That said, yes, with hooks we just give you `const dispatch = useDispatch()` and let you use that as necessary.

- The split across multiple files was never _necessary_. Splitting code like `actions/todos.js`, `reducers/todos.js` , and `constants/todos.js` was _common_ (and admittedly shown in the docs), but Redux itself never cared about how you organized your code at the runtime level. The single-file "ducks pattern" ( https://github.com/erikras/ducks-modular-redux ) was proposed very early on and was always something users could do.

- Labeling "global reducer, serializable state, serializable actions" as "not bringing anything worthwhile" seems like a complete misunderstanding of Redux's design and purpose. Redux was created to give you a consistent data flow architecture, and the ability to make it easier to understand when, why, and how your state gets updated. Centralizing state and having consolidated reducer logic means you _always_ know "go look at the reducers" to see what state the app has, what actions _can_ occur in the app, and how the state gets updated for each action that can occur. Serializable state and actions enable the Redux DevTools, which show you the history of dispatched actions, the action and state contents for each dispatch, and the final resulting state after each dispatch. So, the design constraints are fully intentional to give you the benefits that make the app's behavior easier to understand.

Finally, note that Redux usage patterns changed dramatically in 2019, with the release of our official Redux Toolkit package and the React-Redux hooks API. RTK includes methods that simplify all the common Redux use cases: setting up a Redux store with good defaults, writing reducers with simpler immutable update logic (and getting all the action creators generated for free), patterns like async requests / reactive side effects / normalizing items by ID, and even our RTK Query data fetching layer for fully declarative data fetching and caching.

Redux is not the right choice for all apps, and there's a lot of other good alternative tools in the ecosystem. But Redux's design _is_ very intentional, those constraints were put in place to enable the desired benefits, and Redux usage today is much easier thanks to RTK.

The newish `useReducer` is basically redux but tied into react like in elm.
I'm assuming you mean `useReducer` with `useContext`, but note that they are not a replacement for Redux: https://blog.isquaredsoftware.com/2021/01/context-redux-diff...
That article makes a lot of hand-wavy assertion and makes up strange definitions. userReducer, specially with useContext does absolutely replace Redux and provide mechanism for state management. The article is, in short, just wrong.
The main point is here: https://blog.isquaredsoftware.com/2021/01/context-redux-diff...

Context updates all components while Redux and similar state management tools, because they live outside of React, do not. That's the main reason to use true state management tools over context. If you have a relatively small application or you don't care about that, continue using context. The article is also by a Redux core maintainer so you might call that biased but they know what they're talking about, since they're privy to React design decisions much more than regular users.

> Context updates all components.

All the components that consume it. Not the whole tree under the provider.

It is the whole tree, actually. That's one reason I don't use context.