7 ms·
"Redux is notorious for its boilerplate and has a relatively difficult learning curve. We provided generators for some common templates but it was still one of
by benawad 8y ago
"Redux is notorious for its boilerplate and has a relatively difficult learning curve. We provided generators for some common templates but it was still one of the most challenging pieces and source of confusion while working with React Native."
Interesting to see even Airbnb struggles with Redux
- bpicolo 8y agoThe cognitive overhead of redux ends up being pretty high due to the boilerplate in my opinion. It feels like complexity increases very linearly as project size goes. I've found that MobX translates to a much simpler mental model, though it does have a variety of quirks to deal with that Redux doesn't face (like converting objects to non-observable for test case assertions)
- rawrmaan 8y agoYeah, MobX is significantly easier to reason about, even if it may have a few idiosyncrasies that make debugging more challenging. Also, performance optimization of React components is a cinch with MobX and a nightmare with Redux.
- acemarke 8y agoCan you explain what you mean by "perf optimization is a nightmare with Redux" ? Generally, Redux helps improve performance in a React app, especially as you connect more components.
- rawrmaan 8y agoLet's say you have a component deep in the hierarchy that needs to update based on a small but frequent change in a large object (thousands of keys). With Redux, you have to figure out how to diff the old and new copies of that object to figure out what changed. With MobX, you just observe the value of the exact key you're interested in. That's just one example, but I generally spent a ton of time writing complex shouldComponentUpdate functions and therefore making lots of mistakes with Redux. I've found MobX much more suited to building complex UIs with deep hierarchies and tens to hundreds of total elements on the screen at once, where updating only exactly when necessary is critical. I use MobX for my game Falcross, which I wrote about in the State of React Native 2018 thread from a few days ago: https://news.ycombinator.com/item?id=17316877 https://news.ycombinator.com/item?id=17316877 I initially used Redux, and I found it actually technically impossible to get the game to perform well using Redux. I tried everything.
- acemarke 8y agoI'd agree that MobX generally gives you good performance out of the box, but I'd definitely disagree that Redux's performance situation is a "nightmare". One of the keys to good Redux performance is to connect more components, and have each component only extract a small piece of the state [0]. Using memoized selector functions also helps in most situations [1]. FWIW, there was a really good discussion on the relative strengths and weaknesses of Redux and MobX in regards to performance a while back [2]. [0] https://blog.isquaredsoftware.com/2017/01/practical-redux-part-6-connected-lists-forms-and-performance/ https://blog.isquaredsoftware.com/2017/01/practical-redux-pa... [1] https://blog.isquaredsoftware.com/2017/12/idiomatic-redux-using-reselect-selectors/ https://blog.isquaredsoftware.com/2017/12/idiomatic-redux-us... [2] https://www.reddit.com/r/reactjs/comments/5hf4d4/an_artificial_example_where_mobx_really_shines/ https://www.reddit.com/r/reactjs/comments/5hf4d4/an_artifici... (see the linked article, the Reddit comments, and the links in the comments).
- bpicolo 8y agoI really like that mobx + vuex have their version of "memoized selectors" (computed getters) straight out of the box, fully integrated. They're so insanely useful.
- maga_2020 8y agoI strongly agree with the 'cognitive overhead' comment. I think, a number of challenges that Redux and MobX are intended to address, can potentially be resolved in more elegant and easy manner with the new (16.3.1 and above) Context APIs. ReactNative 55.+ works with 16.3.x and 16.4.0 so these APIs are available to your react native apps now. For example making available global stores to all the components that need them, being able to invoke 'render' on the interested components, when a particular store is being updated -- all of that is being supported. All that without passing the store as property through the hierarchy depth. for the cases where your component relation is 'horizontal', rather than hierarchical. I recommend simply to use pubsub.js. It is a library that has 0 dependencies (rarity in JavaScript ecosystem :-) ). and has both Sync and Async publishing via channels. So that you can pause your publishing to the horizontally-connected components, if you need to, and then resume -- when the publishing is done.
- acemarke 8y agoAs a Redux maintainer, I'd be really interested to know what approaches they used, and what sorts of difficulties they had. (I'll throw out my obligatory comment that you are always welcome to use as much or as little abstraction as you want on top of Redux, and there's plenty of options available to trim down "boilerplate" depending on your situation.)
- deleted 8y ago[deleted]
- msoad 8y agoThose libs add some "magic" which is going against the point of Redux (knowing exactly what's going on). Instead of those abstraction libs I like to use the observable pattern with Rx or MobX
- acemarke 8y agoDepends on what your definition of "magic" is. For example, we specifically have a "Reducing Boilerplate" docs page [0] that talks about writing reusable logic for reducers and action creators, like "higher order reducers" or a `createReducer()` util that accepts a lookup table of action types to handler functions. There's many existing libs that implement this kind of pattern [1]. Beyond that, there's other libraries that provide a higher level of abstraction, like automatically generating logic to handle common use cases (normalizing data, updating certain fields, etc) [2]. Updating data immutably can become complex [3], so there's a lot of immutable update utility libraries out there [4]. I recommend Immer [5], which lets you write normal mutative code but then applies the updates immutably. Finally, there's frameworks built on top of Redux, like Kea and Rematch [6]. So, plenty of options available, depending on what you're comfortable with. [0] https://redux.js.org/recipes/reducing-boilerplate https://redux.js.org/recipes/reducing-boilerplate [1] https://github.com/markerikson/redux-ecosystem-links/blob/master/action-reducer-generators.md https://github.com/markerikson/redux-ecosystem-links/blob/ma... [2] https://github.com/TheComfyChair/redux-scc https://github.com/TheComfyChair/redux-scc , https://github.com/Bloomca/redux-tiles https://github.com/Bloomca/redux-tiles [3] https://redux.js.org/recipes/structuring-reducers/immutable-update-patterns https://redux.js.org/recipes/structuring-reducers/immutable-... [4] https://github.com/markerikson/redux-ecosystem-links/blob/master/immutable-data.md#immutable-update-utilities https://github.com/markerikson/redux-ecosystem-links/blob/ma... [5] https://github.com/mweststrate/immer https://github.com/mweststrate/immer [6] https://github.com/keajs/kea https://github.com/keajs/kea , https://github.com/rematch/rematch https://github.com/rematch/rematch
- tomc1985 8y agoHaving never worked with Redux, what is its point? Is it really so hard to stick app state in a JS object and databind off that?
- acemarke 8y agoYes and no. The main point of Redux is to make your state updates predictable and traceable throughout the codebase. Sure, you can create a global object and stuff your data in there. But, if any random part of the app is allowed to modify that object at any time, then it's a lot harder to understand how your app got into a particular end situation. Redux is based on the "Flux Architecture" concept, and asks you to follow restrictions on how you structure your logic. Only certain functions are allowed to update the state, and in order to run that logic, you create plain JS objects called "actions" that describe some event or update that needs to occur, and ask the update logic to determine the new state values in response. This adds a level of indirection to your code, but it provides a way to log and trace when, where, why, and how a given piece of state got updated. If you've got about 45 minutes, I did a "Redux Fundamentals" presentation at Reactathon a few months ago that walks through the basic principles of Redux. Here's a link to the video and the slides: https://blog.isquaredsoftware.com/2018/03/presentation-reactathon-redux-fundamentals/ https://blog.isquaredsoftware.com/2018/03/presentation-react...
- danenania 8y agoIn a simple app, no. In a really big app with tons of interdependent, asynchronously loaded state? Have fun. Redux definitely has too much boilerplate, but it does an excellent job of keeping functionality decoupled, and on a big project this ends up being way more important. When you do it right, you rarely introduce regressions when working on new features, because almost everything you do is additive: you're adding new state, new actions, new selectors, new sagas, etc., without touching any pre-existing functionality or anything that pre-existing functionality depends on. The alternative is playing an endless game of whack-a-mole as an app gets too large for anyone to keep track of what depends on what.
- molszanski 8y ago
- mychael 8y agoA big contributor to the difficult learning curve in Redux is the very poor naming of things. It's off the charts unintuitive, especially if you're an experienced programmer. I imagine their thought process went like this: Types: People like strongly typed languages, maybe if we call our events "types", they will like Redux more? Reducers: Switch statements are so boring and uncool. Lets call this "reducer" instead of "events switch statement". Store: Lets call the state tree "store". The term "State tree" is too explicit and a core principle of Redux is misdirection. Actions: Mere mortals will associate the term "action" with functions and procedures, but Redux is not for mortals. "Action" will be our term for payload.
- gpmcadam 8y agoGiven that Redux is an implementation of the Flux pattern, your grievances may actually be with the naming conventions in Flux itself. https://facebook.github.io/flux/docs/in-depth-overview.html#content https://facebook.github.io/flux/docs/in-depth-overview.html#...
- acemarke 8y agoThis is the thing that everyone seems to have forgotten. Redux didn't invent these terms out of nothing. Redux was specifically written as an implementation of the Flux Architecture, and the terms "store", "action", and "type" came directly from Flux. The term "reducer" had been in use with Clojure already, I think, and is based on the way these functions have the same signature as a callback you pass to `Array.prototype.reduce`. "State" is a generic term meaning "data in your app", and the term "tree" for a hierarchy of objects has been around for ever. (Oh, and you can write your reducer functions with _whatever conditional logic you want_ - switch statements just happen to be an obvious way to handle multiple values for a single field.) I covered a lot of the history and thought behind Redux's design in my post "The Tao of Redux, Part 1: Implementation and Intent" [0] . Sure, I'd agree that the terms are a lot to take in for a new learner, but claiming these were chosen or made up to make things more confusing is ridiculous. There was a lot of debate over exactly what terms to use during the development process [1] [2] [3], and it was ultimately decided that keeping the Flux-based terminology made the most sense at the time, because most people coming to Redux were familiar with Flux already. Obviously the dev landscape has changed since then, since nobody seems to remember that the original Flux concept existed, but the terms are now set in stone because we've been using them since the beginning. [0] https://blog.isquaredsoftware.com/2017/05/idiomatic-redux-tao-of-redux-part-1/ https://blog.isquaredsoftware.com/2017/05/idiomatic-redux-ta... [1] "reducers": https://github.com/reduxjs/redux/issues/137 https://github.com/reduxjs/redux/issues/137 [2] "state", "store", "dispatch" : https://github.com/reduxjs/redux/issues/113 https://github.com/reduxjs/redux/issues/113 , https://github.com/reduxjs/redux/issues/137 https://github.com/reduxjs/redux/issues/137 [3] "actions" vs "events": https://github.com/reduxjs/redux/issues/384 https://github.com/reduxjs/redux/issues/384 , https://github.com/reduxjs/redux/issues/377 https://github.com/reduxjs/redux/issues/377 , https://github.com/reduxjs/redux/issues/891 https://github.com/reduxjs/redux/issues/891
- BinaryIdiot 8y ago> Interesting to see even Airbnb struggles with Redux I mean even the creator of Redux says you probably don't need to use it or if you do not all of it. It's overly complex for what it is meant to do, IMO. I had issues figuring it out initially and now if I don't touch it for a few months I feel like I have to re-learn how parts of it work because I forget and it doesn't feel intuitive to me.
- danpalmer 8y agoIt's really amazing to see Redux, and then go and use the Elm architecture. The Elm architecture is so simple you could write the API on a business card, and it fundamentally does the same thing, and solves the same problem. There's almost no accidental complexity, only essential complexity. Redux on the other hand feels like there's so much accidental complexity, but it's not even obvious, it's masquerading as essential complexity.
- bigmanwalter 8y agoIt feels like an emperor with no clothes situation. Redux is obviously terrible but the community has adopted it none the less.