Hacker News new | ask | show | jobs
by bengillies 3020 days ago
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 your business logic into these plain functions, then they're really easy to test, reason about, move, refactor, etc.

> What drives people to put all of that into their store?

It's worth pointing out that redux-thunk doesn't move async code into your store. The store (i.e. reducers) is still completely synchronous.

1 comments

> 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)?

> Business logic has no place in your view components, of course, but is quite appropriate in your controller components.

Sure. Where you actually put stuff depends entirely on the complexity of what it is that you're building. If you have an async function that you need to use in several places then it makes sense to keep it separate. If you have several of these then maintaining a separate container component for each view component that needs access to these quickly becomes unmaintainable.

On the other hand, keeping them as separate functions and adding them in via redux `connect` syntax and `mapDispatchToProps` is simple and makes it clear what's going on. In this scenario, the `connect` higher-order-component acts like the container class, but it built up from separate parts depending on what you need.

> redux-thunk seems to encourage that you use it for everything

I don't think this is true. redux-thunk is a piece of middleware and that's pretty much it. It should be used however is most appropriate for your application and your particular use case. Keeping state inside components isn't always appropriate, but isn't always a bad thing either. If one is growing too complicated, then perhaps the other is more appropriate.

I agree that no two applications have the same needs, but async functions (and non-async, for that matter) are naturally separate and reusable, so I'm not sure I am entirely clear on what you are getting at here. What is the benefit of using connect to connect your function and simply calling that function from your controller? Code needed in multiple places should not require redux.