ioof-holdings / redux-subspace

Build decoupled, componentized Redux apps with a single global store
https://ioof-holdings.github.io/redux-subspace/
BSD 3-Clause "New" or "Revised" License
312 stars 33 forks source link

Middleware Compatibility #38

Closed mpeyper closed 5 years ago

mpeyper commented 7 years ago

After the v2 improvements in #34 we are in a better position to support more existing redux middlewares.

This started with redux-saga (which was added in #34), then redux-promise (#36) and now redux-observable (if #37 is merged).

My plan is to try out the most popular middleware and either document that they work, or list any caveats in the redux-subspace documentation (like redux-thunk and redux-promise), and, if required create a compatibility package for them (like redux-saga).

To start with, I want to at least cover the middleware in the ecosystem section of the Redux docs, but also other's as they come on my radar, such as redux-logic which was requested in #30.

This would be a great task for others to get their hands dirty in redux-subspace.

mpeyper commented 7 years ago

Middleware:

Enhancers

mpeyper commented 7 years ago

Updated list with some enhancers as well after the redux-loop addition in #44

jcheroske commented 7 years ago

Man, seeing redux-logic at the bottom of that list is painful. It's the one middleware to rule them all!

mpeyper commented 7 years ago

The order of that list is not indicative of the order they will be looked at... But if it makes you feel better, I'll move it up the list ;)

FWIW, I planned to look at redux-cycles or redux-logic next.

jcheroske commented 7 years ago

I don't want to bash other middlewares, but, having used several of them, I find redux-logic to be a kind of meta-middleware that rolls the functionality of the different ones together into a really nice, seamless whole. I usually write my side-effects using async/await, and it supports that syntax right out of the box. But if I need more power, then I can switch over to rxjs syntax with no pain, while still getting many of the other perks that redux-logic has to offer. I try to spread the word on it, simply because it deserves much more attention. And I'm stoked that it's on your short list!

mpeyper commented 7 years ago

For me, there are pros and cons both ways. It great when something is really flexible and can be used how you want to use it, but it can sometimes become a jack-of-all-trade, master-of-none. Something that is super good at one thing is also great when you're doing that thing, but often falls down when you want to so something slightly left of normal. Of course, it's possible to balance the line between being flexible enough to cover a greater number of cases, without sacrificing features in what you can do, but very few actually pull this off well, or have a massive amount of effort go into maintaining that balance.

In my personal usage of Redux, I actually haven't come across many times that redux-thunk wasn't enough for what I was trying to accomplish.

I look forward to trying redux-logic based on your glowing review. Out of interest, have you tried redux-cycles yet? I've heard a lot of good things about it which is why it's so high on my list of middleware to look at.

mpeyper commented 7 years ago

FYI @jcheroske, I've begun working (in my spare time, so don't get too excited on it being done soon) on a redux-logic wrapper and I have to admit, it's a pretty sweet middleware.

My only complaint (which would literally only be an issue for me) is that there isn't one single place the logic exposes the store (or it's functions), meaning I have to recreate the subspace multiple times (in validate, in transform and in process every time the logic is triggered), so it may add some performance overhead, but in my testing it hasn't been too bad. I'm still coming to grips with how the logic objects work so I may yet find better way.

I do have a quick question on usage for you. According to the usage section of their docs, it seems as though logics are combined through standard array combination:

// in logic.js - combines logic from across many files, just
// a simple array of logic to be used for this app
export default [
 ...todoLogic,
 ...pollsLogic
];
// pollsLogic
export default [
  validationLogic,
  addUniqueId,
  fetchPollsLogic
];

The common pattern with redux-subspace is to wrap each layer with a subspaced function, so which is preffered

// Option 1
export default [
 ...subspaced((state) => state.todos, 'todos')(todoLogic),
 ...subspaced((state) => state.polls, 'polls')(pollsLogic)
];

or

// Option 2
export default [
 subspaced((state) => state.todos, 'todos')(todoLogic),
 subspaced((state) => state.polls, 'polls')(pollsLogic)
];

Basically the only difference is where the spread operators go, but option 2 is probably going to be harder to implement (it will need to return a single logic that can run multiple logics).

With option 1, I think the basic logic (pun intended) would be if an array is provided, an array is returned, but if a single logic is provided a single logic is returned.

Any thoughts and feedback are welcome.

mpeyper commented 6 years ago

The Redux Ecosystem docs have recently been updated (it include redux-subspace not to - YAY!) so I'll try to find some time soon to go through that and see if the list is still valid and add and/or remove any items that make sense to.

FYI, I started looking at redux-logic again recently and it's still giving me some grief. If anyone has experience with it, I'd love some input.

mpeyper commented 5 years ago

I don't see us adding taking on any more official packages to support. I'm more than happy to consider any though, but I'm not going to keep track of them here anymore. Closing.