Live data from Hacker News

Redesigning Redux

medium.com

21–30 of 88 posts

Re: Redesigning Redux

#21
post #6

I've never really understood the point of redux-thunk. But, then, I also don't use asynchronous actions in my datastore . Asynchronous actions feel, to me, that they belong at the component layer where niceties such as spinners are being rendered, and then the backing store is updated with the results of the triggered action. What drives people to put all of that into their store?

Redux is for state management - that could be your data store but many people use it manage their app's UI state as well. Dan Abramov himself has said many times that redux isn't strictly necessary and using local state is fine, but there are some benefits to having a full, serializable application state. You can capture and include it with a bug report/runtime exception for example. Having redux actions dispatched when users interact with your app can also be useful since you get an implicit global event bus. For things like analytics instead of littering calls to your analytics provider in all of your components' click handlers you can write middleware and keep all of that code outside of your presentation/behavior layer.

Re: Redesigning Redux

#22
> You don’t need to understand what a “comonad” is to use jQuery, and you shouldn’t necessarily need to comprehend functional composition to handle state management.

Is there a point to spreading this piece of sage FUD?

It should not be surprising that pure functions + immutable state results in fewer errors.

The "pattern" Redux asks you to use prevents you from shooting your leg off. If you've written a sizeable application that uses global, mutable state the benefits of Redux shouldn't be surprising.

My only gripe with this eco-system is that it constantly comes up with new names and concepts for things that already exist in the FP world. I agree that the math jargon is off-putting but so is having a dozen words for the same concept. I think the latter is worse.

The library described in the article feels less like an abstraction and more like a shuffling around of syntax. Useful but misleading with a title like, Redesigning Redux.

Update: s/grip/gripe

Re: Redesigning Redux

#23
post #6

I've never really understood the point of redux-thunk. But, then, I also don't use asynchronous actions in my datastore . Asynchronous actions feel, to me, that they belong at the component layer where niceties such as spinners are being rendered, and then the backing store is updated with the results of the triggered action. What drives people to put all of that into their store?

Thunk is not about storing async state in the datastore, it's more akin to multithreading in my opinion.

In backend, you might spin up a thread to do expensive operation like API access, and that thread has it's own database connection, to read and persist data.

With thunk, you dispatch a thunk-ed action to do expensive operation like fetching data from backend, and that action has it's own access to redux in form of `dispatch` / `getState` arguments.

In the end, my component calls `fetchData` function upon mounting. And the logic dealing with making multiple requests due to paging, or re-trying on errors then lives its own life inside a thunk action, independent from the component that spawned it.

Re: Redesigning Redux

#24
post #6

I've never really understood the point of redux-thunk. But, then, I also don't use asynchronous actions in my datastore . Asynchronous actions feel, to me, that they belong at the component layer where niceties such as spinners are being rendered, and then the backing store is updated with the results of the triggered action. What drives people to put all of that into their store?

The problem with putting all async code directly into components is that often, async code is business logic or some other non-view-layer thing that doesn't really belong in a component. The benefit of redux-thunk (and there are obviously other alternatives that provide the same value) is that it lets you write plain functions that have nothing to do with the store, and nothing to do with components. If you put all y…

> async code is business logic or some other non-view-layer thing that doesn't really belong in a component.

In many React applications, components are separated into independent "controller"-layers and "view"-layers (containers and components are nomenclature I see occasionally, but the important takeaway is that both inherit from the React component class). Business logic has no place in your view components, of course, but is quite appropriate in your controller components. I don't think component implies view layer here. Even redux actions, when used, are appropriately called from the controller layer and not the view layer. Redux doesn't change anything about logical separation of concerns.

When the Flux pattern was originally introduced, it was driven home that it should not be used for everything. redux-thunk seems to encourage that you use it for everything. What do you use when global state is not necessary (or wanted)?

Re: Redesigning Redux

#25
post #6

I've never really understood the point of redux-thunk. But, then, I also don't use asynchronous actions in my datastore . Asynchronous actions feel, to me, that they belong at the component layer where niceties such as spinners are being rendered, and then the backing store is updated with the results of the triggered action. What drives people to put all of that into their store?

> Asynchronous actions feel, to me, that they belong at the component layer where niceties such as spinners are being rendered, and then the backing store is updated with the results of the triggered action.

This is exactly how thunks work, you just fire them from your component as a Redux action. I use thunks primarily for when an action needs to get data from an API and insert it into the store (e.g. on login).

Inverting the question, why would I want my presentational components to do a bunch of extra work beyond presenting? Calling an API is not presentational.

Re: Redesigning Redux

#26
post #6

I've never really understood the point of redux-thunk. But, then, I also don't use asynchronous actions in my datastore . Asynchronous actions feel, to me, that they belong at the component layer where niceties such as spinners are being rendered, and then the backing store is updated with the results of the triggered action. What drives people to put all of that into their store?

Part of the idea behind Redux is to keep components as pure as possible and limit side effects to one place, usually actions. You keep all async actions in components?

I write separate business logic into which are passed their dependencies and/or the data to operate on. If you have a defined API client, you can pass that to your business logic and let it work with the API client, but to do so means that in testing you have to mock your API client. So my business logic objects tend to work on groups of domain objects (in a functional manner, usually using ImmutableJS these days).

Functional-core, imperative-shell design suggests to then use this functional core within a shell of code that handles IO, handles failure cases--effectively, anything that can fail belongs here. To me, that's the React component; I don't view React as "functional", as it's got multiple types of state even separate from Redux (and this is not a demerit, IMO). The onClick handler of a React button is no different from the command handler for a CLI application. The code in that handler makes requests of its API client (which I typically inject through context and my own HOC--like I said, React's statefulness doesn't bug me at all), it performs business logic functions on the data yielded from its API client, and it stores the result (typically with a onComplete method or the like, so my redux-connected component can dispatch an action).

I'm amenable to other ways to do that data routing (because that's really all any of this is), I just don't see why the state store is where this routing should be done and see a lot of reasons around testing and failure-rescue and general code cleanliness why I wouldn't. If you were to make HTTP requests in your SQL datastore I'd be remarkably concerned for your sanity; I don't think it makes any more sense to do so in a Redux store.

Re: Redesigning Redux

#27

The strength of redux is that all your interactions with it are through functions. Redux today is far better than the Redux of yesteryear thanks to things like ReSelect, Thunks, Sagas, Higher Order Components etc. All these things augment Redux, and they can do so because of Redux's open embrace of the humble pure function. Once you commit to a config based approach, you're basically closing the door to a future you…

> The strength of redux is that all your interactions with it are through functions

I think it's the other way around: The greatest weakness of Redux is that (unnecessarily) message passing instead of function calls are used.

Why do a `store.dispatch({type: 'INCREMENT', value: 10})` when it could be a `store.count.increment(10)`? In basically all cases every action is handled by exactly one reducer so just let the reducer be an object with methods instead of a big switch function operating on string constants.

Re: Redesigning Redux

#28

> You don’t need to understand what a “comonad” is to use jQuery, and you shouldn’t necessarily need to comprehend functional composition to handle state management. Is there a point to spreading this piece of sage FUD? It should not be surprising that pure functions + immutable state results in fewer errors. The "pattern" Redux asks you to use prevents you from shooting your leg off. If you've written a sizeable app…

> My only gripe with this eco-system is that it constantly comes up with new names and concepts for things that already exist in the FP world.

I agree, but I think it's easy to see how it happens. It's an impediment to adoption of the project if people don't understand what you're talking about, so simplistic shorthand is used initially to get people up to speed, and then you find that your temporary names have become engraved in stone for the vast majority of your users. People being how they are, you're just as likely to get them to change editors as change terminology at that point.

Re: Redesigning Redux

#29
post #25
post #6

I've never really understood the point of redux-thunk. But, then, I also don't use asynchronous actions in my datastore . Asynchronous actions feel, to me, that they belong at the component layer where niceties such as spinners are being rendered, and then the backing store is updated with the results of the triggered action. What drives people to put all of that into their store?

> Asynchronous actions feel, to me, that they belong at the component layer where niceties such as spinners are being rendered, and then the backing store is updated with the results of the triggered action. This is exactly how thunks work, you just fire them from your component as a Redux action. I use thunks primarily for when an action needs to get data from an API and insert it into the store (e.g. on login). Inv…

I think calling components "presentational" is an abuse of the term. It is all imperative facade at any meaningful level. The relationship of components to the user interactions triggered through them is not materially, to me, different from issuing a command from a CLI. As such, I tend to constrain imperative, this-can-fail activity to that layer rather than chucking it into my datastore.

Re: Redesigning Redux

#30
post #21
post #6

I've never really understood the point of redux-thunk. But, then, I also don't use asynchronous actions in my datastore . Asynchronous actions feel, to me, that they belong at the component layer where niceties such as spinners are being rendered, and then the backing store is updated with the results of the triggered action. What drives people to put all of that into their store?

Redux is for state management - that could be your data store but many people use it manage their app's UI state as well. Dan Abramov himself has said many times that redux isn't strictly necessary and using local state is fine, but there are some benefits to having a full, serializable application state. You can capture and include it with a bug report/runtime exception for example. Having redux actions dispatched w…

> full, serializable application state

Perhaps I'm dense, but you can serialize the current running state of a Promise in redux-thunk?

Post reply on HN