Description
Inspired by this little tweetstorm.
Problem: Side Effects and Composition
We discussed effects in Redux for ages here but this is the first time I think I see a sensible solution. Alas, it depends on a language feature that I personally won’t even hope to see in ES. But would that be a treat.
Here’s the deal. Redux Thunk and Redux Saga are relatively easy to use and have different pros and cons but neither of them composes well. What I mean by that is they both need to be “at the top” in order to work.
This is the big problem with middleware. When you compose independent apps into a single app, neither of them is “at the top”. This is where the today’s Redux paradigm breaks down—we don’t have a good way of composing side effects of independent “subapplications”.
However, this problem has been solved before! If we had a fractal solution like Elm Architecture for side effects, this would not be an issue. Redux Loop implements Elm Architecture and composes well but my opinion its API is a bit too awkward to do in JavaScript to become first-class in Redux. Mostly because it forces you to jump through the hoops to compose reducers instead of just calling functions. If a solution doesn’t work with vanilla combineReducers()
, it won’t get into Redux core.
Solution: Algebraic Effects in JavaScript
I think that what @sebmarkbage suggested in this Algebraic Effects proposal is exactly what would solve this problem for us.
If reducers could “throw” effects to the handlers up the stack (in this case, Redux store) and then continue from they left off, we would be able to implement Elm Architecture a la Redux Loop without the awkwardness.
We’d be able to use vanilla combineReducers()
, or really, any kind of today’s reducer composition, without worrying about “losing” effects in the middle because a parent didn’t explicitly pass them up. We also would not need to turn every reducer into a generator or something like that. We can keep the simplicity of just calling functions but get the benefits of declaratively yielding the effects for the store (or other reducers! i.e. batch()
) to interpret.
I don’t see any solution that is as elegant and simple as this.
It’s 2am where I live so I’m not going to put up any code samples today but you can read through the proposal, combine it with Redux Loop, and get something that I think is truly great.
Of course I don’t hold my breath for that proposal to actually get into ES but.. let’s say we could really use this feature and Redux is one of the most popular JavaScript libraries this year so maybe it’s not such a crazy feature as one might think at first 😄 .
cc people who contributed to relevant past discussions: @lukewestby @acdlite @yelouafi @threepointone @slorber @ccorcos