Live data from Hacker News

Redesigning Redux

medium.com

71–80 of 88 posts

Re: Redesigning Redux

#71

Earlier quoted context omitted.

One of the original reasons for message passing is that multiple reducers can respond to the same action. There have been many libraries since the beginning that try to shrink that relationship (ex reducks), but I never understood it, my code is replete with multiple responders.

> my code is replete with multiple responders Thanks for your input! Do you mind giving 2-3 examples of good uses of multiple reducers for the same action?

One example is fetching data, often it is more effecient to request data in a certain way, but the app needs it represented differently, multiple reducers can respond to the same payload and take what they need.

Another example is url updates, I use state-driven-routing and when a url update happens many reducers need to respond to get the pieces of state they are concerned about.

Another example is a login status change, many reducers may need to update themselves if a user logs in our logs out.

It's the difference between having tons of highly specific 1:1 actions getting called from the action creator with their relationship to the root action obfuscated vs. having 1 action that many respond to with their relationship to that action clearly denoted.

To take it a bit further, it reminds me of refactoring vs adding another "if" statement - the former requires comprehensive understanding of the holistic purpose of the system with the dependent relationships properly defined (anti-fragile), whereas the latter is a temporary bandaid that can be implemented with less thought (and the sideeffects that come with it).

Re: Redesigning Redux

#72

Earlier quoted context omitted.

One of the original reasons for message passing is that multiple reducers can respond to the same action. There have been many libraries since the beginning that try to shrink that relationship (ex reducks), but I never understood it, my code is replete with multiple responders.

> my code is replete with multiple responders Thanks for your input! Do you mind giving 2-3 examples of good uses of multiple reducers for the same action?

Middleware. A UI events logger for example. Or finishing a network request may need to close some part of tge Ui and also trigger a reload somewhere else.

Re: Redesigning Redux

#73
Can someone explain to me why someone would choose Redux over something like MobX ?

I feel like implements an action for each modification of state (or group of modifications) requires a lot of boilerplate code. In MobX, you treat your data tree as a separate entity, and simply modify it. The UI is automatically updated whenever it needs to.

Mobx isn't bad performance-wise, I think, since it only re-renders the components that are listening to the modified variables when a modification occurs.

The only advantage I see is being able to rewind the state store, which can be quite cool when debugging.

I have done some medium-sized application (only games), and I don't think I've run into any performance or readability problem with MobX. I've never done web apps with a team, though, but I don't think Redux would specially make it easier to work with other programmers.

Re: Redesigning Redux

#74
post #67
post #54

Earlier quoted context omitted.

One approach is to write a reducer which has `isWaiting`, `error`, `finished` bools (in addition to whatever data said promise eventually modifies), or something similar, and programmatically update them in your actions/thunks. This effectively tracks the state of the promise (resolved/not resolved, error).I think the Flux "standard action" puts something similar in the action object - not sure what they do with it t…

Yeah I get that, but then the application state isn't serialized in a usable form. If you re-load that state, you have half-open, "pending" operations. If an idea of Redux is that serializable state is a good thing, then redux-thunk seems inimical to that.

Why would you serialize a pending network request? I use a property whitelist in my serializer that drops any application state not related to the business logic. Also, I don't use redux-thunk, I move all async operations to middleware and action creators are synchronous and declarative. For example, an API request will be defined in an action creator as an endpoint, http method, and request body, and the middleware will intercept this, make the API calls, and dispatch "pending" and "success/failure" actions. It scales extremely well and I don't know why people don't use custom middleware more often. The currying is a little confusing if you've never been exposed to it before, but the concept is no different than middleware in pretty much any http framework. I have yet to run into a problem that can't be solved by a custom middleware chain more cleanly than crazy async action frameworks like saga (I know saga works great for some folks but I think the cognitive overhead makes it of questionable utility when a promise chain in middleware can solve the same problem without requiring everyone on your team learn yet another library).

Re: Redesigning Redux

#75
post #74
post #67

Earlier quoted context omitted.

Yeah I get that, but then the application state isn't serialized in a usable form. If you re-load that state, you have half-open, "pending" operations. If an idea of Redux is that serializable state is a good thing, then redux-thunk seems inimical to that.

Why would you serialize a pending network request? I use a property whitelist in my serializer that drops any application state not related to the business logic. Also, I don't use redux-thunk, I move all async operations to middleware and action creators are synchronous and declarative. For example, an API request will be defined in an action creator as an endpoint, http method, and request body, and the middleware…

> Why would you serialize a pending network request?

I wouldn't. That's why I wouldn't put anything related to it in my Redux state!

But, like, I'm willing to be convinced. This is just where I'm at right now. Maybe your method would make more sense than redux-thunk does to me; have you written anything in more detail about this? (I'm not scared of middlewares, I've used Redux and middlewares even in non-web contexts, so intuitively this at least sounds more promising.)

Re: Redesigning Redux

#76
post #56

While Redux is great because it enforces a single source of truth, the whole thing with "actions" and "reducers" in Redux is a huge source of boilerplate. In almost every Redux project I have worked on, developers bring in some weird scheme to reduce the boilerplate load of having to come up with a bunch of events when all that anyone wants to do is call some functions. The fact that Redux forces you to use events to…

The issues with Redux Sagas and etc. was unavoidable, because Redux didn't take an early stance on how to handle actions which weren't ready right away, something the article author calls differed actions. It's not because of the overabundance of boilerplate, but the LACK of guidance in the existing boilerplate.

Re: Redesigning Redux

#77

Earlier quoted context omitted.

> my code is replete with multiple responders Thanks for your input! Do you mind giving 2-3 examples of good uses of multiple reducers for the same action?

One example is fetching data, often it is more effecient to request data in a certain way, but the app needs it represented differently, multiple reducers can respond to the same payload and take what they need. Another example is url updates, I use state-driven-routing and when a url update happens many reducers need to respond to get the pieces of state they are concerned about. Another example is a login status ch…

> when a url update happens many reducers need to respond

Wouldn't the components handle this change and dispatch any actions needed?

> a login status change, many reducers may need to update themselves if a user logs in our logs out.

Again, couldn't this be handled at the component level? It seems risky to have multiple sources of truth for data.

Re: Redesigning Redux

#78

Can someone explain to me why someone would choose Redux over something like MobX ? I feel like implements an action for each modification of state (or group of modifications) requires a lot of boilerplate code. In MobX, you treat your data tree as a separate entity, and simply modify it. The UI is automatically updated whenever it needs to. Mobx isn't bad performance-wise, I think, since it only re-renders the compo…

> The only advantage I see is being able to rewind the state store

Another big one is being able to restore the state. In Redux, it's just one giant object that can be easily serialized and use in the future. With Mobx, I'm guessing you have to write deserialize logic for your various classes.

Re: Redesigning Redux

#79
post #75
post #74

Earlier quoted context omitted.

Why would you serialize a pending network request? I use a property whitelist in my serializer that drops any application state not related to the business logic. Also, I don't use redux-thunk, I move all async operations to middleware and action creators are synchronous and declarative. For example, an API request will be defined in an action creator as an endpoint, http method, and request body, and the middleware…

> Why would you serialize a pending network request? I wouldn't. That's why I wouldn't put anything related to it in my Redux state! But, like, I'm willing to be convinced. This is just where I'm at right now. Maybe your method would make more sense than redux-thunk does to me; have you written anything in more detail about this? (I'm not scared of middlewares, I've used Redux and middlewares even in non-web contexts…

I agree, I'm pretty strict about keeping UI state out of the store, but when you need to coordinate a bunch of components based on the status of network API requests and you already have a global message bus available...

I've created a gist[1] with some snippets from a current project; it's still alpha, but you can get a general feeling for how the data flow works. I would clean it up a bit if I were officially releasing it to the public, but I'm definitely interested in feedback if anyone thinks I'm doing it ALL WRONG. :)

[1]: https://gist.github.com/parkerault/9dc7e825cc9a62b5efa8a4c1c...

Edit: regarding serializing state; I don't know how others handle it but I subscribe a localStorage writer to the store that only gets called when the store is changed, not when an action dispatches, so if an action creator dispatches a function to redux-thunk, the action doesn't get serialized, just the resulting store after the reducers do their thing. Do you have any examples of actions themselves getting serialized? I believe when Abramov talks about keeping the state serializable in the redux docs he's referring to the store itself; as far as I know anything goes in the actions themselves.

Re: Redesigning Redux

#80
post #77

Earlier quoted context omitted.

One example is fetching data, often it is more effecient to request data in a certain way, but the app needs it represented differently, multiple reducers can respond to the same payload and take what they need. Another example is url updates, I use state-driven-routing and when a url update happens many reducers need to respond to get the pieces of state they are concerned about. Another example is a login status ch…

> when a url update happens many reducers need to respond Wouldn't the components handle this change and dispatch any actions needed? > a login status change, many reducers may need to update themselves if a user logs in our logs out. Again, couldn't this be handled at the component level? It seems risky to have multiple sources of truth for data.

> multiple sources of truth

There wouldn't be more than a single source of a given truth, the multiple responders pull different truths relevant to them, the combination of which making the complete app state.

Post reply on HN