10 ms·
I never understood why Redux became so popular. It basically tries to enforces a few old ideas, pure functions, message passing and immutability, with no help
by noncoml 9y ago
I never understood why Redux became so popular.
It basically tries to enforces a few old ideas, pure functions, message passing and immutability, with no help from the language, which results in verbose and ugly code.
`a.b = c` becomes `Object.assign({}, a, { b = c })`
and
`object.method(data)` becomes `store.dispatch({type: METHOD, data})` with the implementation code of the "object" being a huge "switch" statement.
If you want immutability, pure functions and message passing, then why not use a language that is build around them and make your life easier? Clojurescript maybe?
Also having a single store for all your data, definitely doesn't help with speed as a single event suddenly becomes an O(LogN) operation in the best case.
- acemarke 9y agoSeveral reasons why it's popular: - It has helped many developers organize their "write logic" and state management, and made it easier to test that code - Time travel debugging is a fantastic tool for understanding what happens in your application - One of my favorite quotes: "Redux is a generic framework that provides a balance of just enough structure and just enough flexibility. As such, it provides a platform for developers to build customized state management for their use-cases, while being able to reuse things like the graphical debugger or middleware." - And it doesn't hurt that Dan Abramov is a well-known figure in the React community, and an incredibly helpful and friendly person too. No, Javascript doesn't have immutability built-in (sadly), but that doesn't mean you should totally give up on applying those principles in Javascript code. There's WAY more developers writing JS than Clojurescript, and those devs can still make use of tools like Redux in their applications. Besides, there's a variety of approaches for handling data immutably, whether it be `Object.assign`, the Stage 3 object spread operator, Immutable.js, or the many immutable update utility libraries out there. Your comment about speed doesn't make sense. A few function calls and switch statements will execute quickly overall, and perf benchmarks will show that your reducer logic is almost never going to be the bottleneck in a Redux application. Some links for further related reading: - https://medium.com/@dan_abramov/you-might-not-need-redux-be46360cf367 https://medium.com/@dan_abramov/you-might-not-need-redux-be4... - http://redux.js.org/docs/faq/Reducers.html#reducers-use-switch http://redux.js.org/docs/faq/Reducers.html#reducers-use-swit... - http://redux.js.org/docs/faq/Performance.html#performance-all-reducers http://redux.js.org/docs/faq/Performance.html#performance-al... - https://github.com/markerikson/react-redux-links/blob/master/immutable-data.md https://github.com/markerikson/react-redux-links/blob/master... - https://github.com/markerikson/redux-ecosystem-links/blob/master/immutable-data.md https://github.com/markerikson/redux-ecosystem-links/blob/ma...
- gyrgtyn 9y agoWhen do you get to write `a.b = c` in react? Not with `setState`
- noncoml 9y agoDon't you use `setState` only for UI state, i.e. react components? As far as I understand it with redux you end up having all of your application's state in the store. Unless you split it?
- acemarke 9y agoIt's up to you how much of your data you put into Redux. Quoting the Redux FAQ at http://redux.js.org/docs/faq/OrganizingState.html#organizing-state-only-redux-state http://redux.js.org/docs/faq/OrganizingState.html#organizing... : > Using local component state is fine. As a developer, it is your job to determine what kinds of state make up your application, and where each piece of state should live. Find a balance that works for you, and go with it. Some common rules of thumb for determining what kind of data should be put into Redux: > - Do other parts of the application care about this data? > - Do you need to be able to create further derived data based on this original data? > - Is the same data being used to drive multiple components? > - Is there value to you in being able to restore this state to a given point in time (ie, time travel debugging)? > - Do you want to cache the data (ie, use what's in state if it's already there instead of re-requesting it)? I've seen some people say that you should put literally every single value in your app into Redux. You certainly _can_ do that, but I would see it as overkill. I'm much more pragmatic about it - put it into Redux if it makes sense to, per the rules of thumb in the FAQ.
- noncoml 9y ago> Some common rules of thumb for determining what kind of data should be put into Redux: > > - Do other parts of the application care about this data? > - Do you need to be able to create further derived data based on this original data? > - Is the same data being used to drive multiple components? > - Is there value to you in being able to restore this state to a given point in time (ie, time travel debugging)? > - Do you want to cache the data (ie, use what's in state if it's already there instead of re-requesting it)? Won't having half your state outside the store and the other half inside add unneeded complexity and make your code even more difficult to read?
- danmaz74 9y ago> Also having a single store for all your data, definitely doesn't help with speed as a single event suddenly becomes an O(LogN) operation in the best case. I'm curious - why do you say O(LogN)?
- Spivak 9y agoHash lookup on the total number of events. But in JS this is basically dust given how often this occurs.
- acjohnson55 9y agoHash lookup is O(1)
- learc83 9y agoWith a perfect hash function. But it's still going to be closer to O(1) than O(log n)
- noncoml 9y ago> O(LogN) To reconstruct your store state, which is basically a hard-coded tree structure.
- sillysaurus3 9y agoWhy is it a tree structure? Why not just allocate an array and append at the end, which is O(1)?
- acemarke 9y agoRedux's `createStore` function doesn't care what value your root reducer returns - it could be plain JS objects or arrays, a single primitive value, Immutable.js objects, or even class instances. However, the common (and suggested) approach is to use the included `combineReducers` utility, which expects that your root state value is a plain JS object, and you can continue to use `combineReducers` to set up handling for nested state values. So yes, a typical Redux app state is indeed an object with various amounts of data attached to the state tree.
- nemothekid 9y ago>Clojurescript maybe? Well Redux is a 'port' of Om from Clojurescript to native JS.
- iammiles 9y agoInteresting! Do you have any source for this? According to the Redux page, it only claims to take inspiration from Elm and Flux[1]. [1] http://redux.js.org/#influences http://redux.js.org/#influences
- benjaminjackman 9y agoJust a tip to make that syntax a bit less ugly[0] Using babel / typescript `a.b = c` becomes `Object.assign({}, a, { b = c })` can be written as `{...a, b: c}` (this desugars in typescript to) `Object.assign({}, a, { b: c });` [1] (note also you had a minor typo there with equal sign {b=c} should be a colon, I feel like I make that mistake multiple times per day when writing typescript / javascript, having two different assignment operator characters in the language is not good imho. i'd prefer if it was all just `=`, that will never change at this point though. ) For your seconds example, `store.dispatch({type: METHOD, data})` perhaps the Proxy object[2] (which allows for delegation, method_missing like functionality) could be used to turn the calls back into store.method(data) 0: Beauty is in the eye of the beholder as they say. 1: https://www.typescriptlang.org/play/#src=const%20a%20%3D%20%7B%20b%3A%201%20%7D%0D%0Aconst%20c%20%3D%202%0D%0A%0D%0Aconst%20x%20%3D%20%7B%20...a%2C%20b%3A%20c%20%7D https://www.typescriptlang.org/play/#src=const%20a%20%3D%20%... 2: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
- jtmarmon 9y agojust to be pedantic: object rest spread[1] is a JS feature implemented by babel, not really a typescript feature [1] https://babeljs.io/docs/plugins/transform-object-rest-spread/ https://babeljs.io/docs/plugins/transform-object-rest-spread...
- deleted 9y ago[deleted]
- mercer 9y agoJust to clarify (and pile on more pedantry?): it's a JS feature that is also implemented by TS, so while you're correct that it's not a TS feature, it's also not particular to Babel. In fact, sometimes I like to use TS because it allows me to skip the Babel part of the process entirely.
- deleted 9y ago[deleted]
- 9y ago
- fineline 9y agoI have a similar feeling about Vuex in the Vue world. Trying to recreate the Elm architecture without Elm ends up being a bit awkward. It's not just immutability and pure functions, as others have noted, it's even more down to a lack in JavaScript of algebraic data types (tagged unions) and pattern matching. Without those, and other Elm language features, you end up getting some quite obscure looking and verbose code and "magic" strings all of which is difficult to type-check (e.g. Flow). Good old-fashioned singleton state modules work better for me.
- woah 9y agoLooks like you're not actually using the language right
- underwater 9y agoA dispatch is not really equivalent to a method call. A reducer can't have side effects, and must be synchronous. So you can be certain that the state is consistent immediately after the dispatch returns. If you have complex action dispatchers the asynchronous logic is still contained in a single function. This is easier to test than a set of loosely coupled data objects that are firing of async events and calling each other through multiple levels of indirection.
- kevincennis 9y agoNot to nitpick, because I believe I understand what you mean – but one of the things that bugs me about Redux is that a reducer absolutely CAN have side-effects. They're just "not supposed to". So all it takes is one mistake or one new developer or whatever and suddenly all your assumptions break.
- doque 9y agoIt's one of the essentials principles of redux [1] that reducers must be pure functions without side effects. If you violate that principle, then yes, your assumptions break. That's why you should keep it in mind. You can't really blame the framework if you purposely go against its basic rules. [1] http://redux.js.org/docs/introduction/ThreePrinciples.html#changes-are-made-with-pure-functions http://redux.js.org/docs/introduction/ThreePrinciples.html#c...
- kevincennis 9y agoI get it. I really do. I just wish they had a reasonable way to _enforce_ those rules (though I understand it's not really possible) – or at least make people really go out of their way to break convention.
- acemarke 9y agoYep - I pointed this out in my post "The Tao of Redux, Part 1 - Implementation and Intent": http://blog.isquaredsoftware.com/2017/05/idiomatic-redux-tao-of-redux-part-1/ http://blog.isquaredsoftware.com/2017/05/idiomatic-redux-tao.... Those "Three Principles" are statements of intent, but not literal technical limitations.
- danesparza 9y agoRedux is an implementation of Flux. I don't use Redux, but the original Facebook engineering announcement videos helped me understand React and Flux tremendously: https://www.youtube.com/watch?v=nYkdrAPrdcw https://www.youtube.com/watch?v=nYkdrAPrdcw If you're talking about Redux specifically -- I agree with you. I think it's ugly and confusing.
- moretti 9y agoRedux is not an implementation of Flux. These two blog posts explain the main differences: https://code-cartoons.com/a-cartoon-guide-to-flux-6157355ab207 https://code-cartoons.com/a-cartoon-guide-to-flux-6157355ab2... https://code-cartoons.com/a-cartoon-intro-to-redux-3afb775501a6 https://code-cartoons.com/a-cartoon-intro-to-redux-3afb77550...
- danesparza 9y agoI stand corrected. Thanks for these posts!
- acemarke 9y agoRedux absolutely _is_ an implementation of the Flux Architecture. I've described it as "Flux taken to its logical conclusion". If you read my post "The Tao of Redux, Part 1 - Implementation and Intent" [0], I quote several comments and pieces of early documentation that back up Redux's Flux heritage. Redux inherited the idea of plain action objects with a `type` field, action creators, and the concept of "dispatching" [0] http://blog.isquaredsoftware.com/2017/05/idiomatic-redux-tao-of-redux-part-1/ http://blog.isquaredsoftware.com/2017/05/idiomatic-redux-tao...