vigetlabs / microcosm

Flux with actions at center stage. Write optimistic updates, cancel requests, and track changes with ease.
http://code.viget.com/microcosm/
MIT License
487 stars 29 forks source link

Action resolve resets action open. #433

Closed engleek closed 6 years ago

engleek commented 6 years ago

I'm trying to write an action/domain which displays file upload with optimistic updates. When the action is opened the item is added to state, but on resolve it just disappears again.

I've written a minimal example based on the planet examples at https://codepen.io/engleek/pen/xXjYgz which pushes an action with open/resolve and logs state/actions to console.

When the action opens, the planet is added to the list, but after the action is resolved the list is empty again.

I'm not entirely sure what I'm doing wrong. Do I need to add the planet first when the action opens, then again when the action resolves? This seems like an unnecessary extra step.

Using Microcosm 12.12.2.

nhunzaker commented 6 years ago

Hey @engleek!

That's correct, you would need an open and done handler. This is so that any work you've done in open that needs to be discarded when the action completes is taken care of automatically.

I've forked/updated your codepen to demonstrate this: https://codepen.io/nhunzaker/pen/boMvBo, but the gist of it is:

add(planets, name) {
    return planets.concat({ name, loading: true });
},

done(planets, name) {
  return planets.concat({ name })
},

register() {
  return {
    [addPlanet]: {
      open: this.add,
      done: this.done,
    },
  };
}

Basically, the open state gets rolled back and the done handler applies on top. Ideally you don't have to worry about the prior state, just worry about how to apply changes as actions come in. Still, I can see how this feels unnecessary. I'm definitely open to exploring ways that we can reduce some of this setup.

engleek commented 6 years ago

Wow, quick answer!

Okay I see. It's more a placeholder than an optimistic update. Using a rollback is a clever idea. I'm guessing it makes cancelling any changes much easier. I think I misunderstood it because of being used to Redux, where all state changes depend entirely on reducers.

My only concern would be costly re-renders for state which hasn't in fact changed, but that shouldn't be too much of an issue.

nhunzaker commented 6 years ago

My only concern would be costly re-renders for state which hasn't in fact changed, but that shouldn't be too much of an issue.

It ends up not being a huge issue because the loading state field change ends up triggering a re-render anyway. Also rollbacks occur on an action-by-action basis and there is some logic to prevent action handlers from one domain invalidating another (so like rolling back gizmos doesn't cause a recalculation of gadgets)

Happy coding!