stutrek / redux-marionette

Because it's time to start that big migration
33 stars 4 forks source link

Very cool solution! #2

Closed AndrewHenderson closed 8 years ago

AndrewHenderson commented 8 years ago

It's nice to find someone working on the same problem!

I work on a very large Marionette app. The dispersion of state throughout the app has become very difficult to manage.

I think the predictability of React/Redux is great, so I began experimenting to recreate their features in a Marionette app. I learned a lot, which I think is why I can appreciate your solution.

I'm going to try out your code. Hopefully, we can replace the Marionette views with React at some point, but that will probably be a long way out, so this might be a great interim tool.

Here are links to my experiments. Hopefully you'll find them interesting!

Codepen: http://codepen.io/AndrewHenderson/pen/rrvdpZ?editors=1010 Mariodux: Marionette, Redux and morphdom: https://github.com/AndrewHenderson/mariodux

stutrek commented 8 years ago

I'm glad you like it! I agree with your shift in mindset, it makes things a lot easier. Your codepen is a lot like how we ended up handling the interface from redux to marionette. Instead of having models listen we ended up with a big app level reducer that triggers changes to our Marionette app.

In my opinion, the thing that will make any transition harder is holding on to old conventions and code. Is there a reason your codepen uses its own store instead of a normal redux store and action spec?

AndrewHenderson commented 8 years ago

Your codepen is a lot like how we ended up handling the interface from redux to marionette

Exactly, it seems we arrived at the same conclusion! 😄

Is there a reason your codepen uses its own store instead of a normal redux store and action spec?

I was presenting the approach to our team and didn't want to overcomplicate things by introducing Redux. I'm definitely in favor of using Redux for the store in a full-fledged solution.

I've found it hard to convince engineers who've been working on Backbone for some time to shift their mindset from pub/sub to reducers – which is why I like how you've abstracted away the concern of keeping the global store in sync with the view's models/collections.

A major sticking point for developers has been the way Redux deals with async by placing isFetching booleans on the state object in order to avoid duplicate calls if the state changes in the interim.

Because of that, I said views can no longer interact with their model directly. Specifically functions like model.fetch() within the view were not allowed in my solutions.

How do you see your solution handling model.fetch()? Would those be handled in the actions or would the view call model.fetch() and the middleware deal with syncing with the store?

stutrek commented 8 years ago

We use a promise middleware and do the isFetching thing. In practice it's no worse than backbone, and far better as a practice because empty collection views are ignorant to the fetching state, and determining if something needs to be fetched is surprisingly hacky. However, it's very hard to convince a person of that.

Before starting this I solved the fetch issue by abstracting out how our data gets fetched and adding a client side cache, originally it was because we were double fetching all over the place. I created a repository of services, one for each one of our endpoints. Each one has its own cache mechanism and each call returns a promise. Then I made a backbone mixin to replace the normal XHR stuff backbone does with the services. At that point we didn't need to worry about duplicate calls, so any time one changed the other could just refetch. This isn't open source, I have the start of an open source version, I may do that soon.

I didn't realize how important the fetch issue is until you said this, even though a developer that started during the migration pointed it out to me.

stutrek commented 8 years ago

Also, I think you should go for the redux action spec. It's better to be able to point to something popular as why you're doing something rather than trying to sell your own invention.

AndrewHenderson commented 8 years ago

I created a repository of services, one for each one of our endpoints. Each one has its own cache mechanism and each call returns a promise

We did exactly that! We called it our Data layer. It's a Marionette app that caches models and collections and gets used as an event bus to return a promise.

Then I made a backbone mixin to replace the normal XHR stuff backbone does with the services

We didn't do that, unfortunately.

We use a promise middleware and do the isFetching thing

Cool. Is this an open source project?

stutrek commented 8 years ago

Here's our mixin, service.load is where it does stuff. https://gist.github.com/stutrek/bb6ae1d45a849226bf02c18ef31b75c3

We use this: https://github.com/pburtchaell/redux-promise-middleware

but if I was to do it again I'd make one that has that status in the meta so we could use symbols as action types, and add an id in there too to avoid race conditions. It's surprisingly easy to make middleware.

AndrewHenderson commented 8 years ago

I'd make one that has that status in the meta so we could use symbols as action types, and add an id in there too to avoid race conditions

I don't think I fully understand the problem you're describing without having used the middleware.

stutrek commented 8 years ago

Thanks for the good conversation, I'm closing this issue because it wasn't really one to begin with.