vigetlabs/microcosm

Watching for specific repo changes with repo.observe()

Closed this issue · 3 comments

I want to make it easier to subscribe to specific state changes in Presenters. I also want to use Observables as the communication interface between more parts of Microcosm.

I would like to see an Observable form of repo.on('change:?key'). This could be used directly inside of Presenters:

class Planets extends Presenter {
  getModel() {
    return {
      planets: this.repo.observe('planets')
    }
  }
}

Additionally, we could add basic data processing:

function getBigPlanets(planets) {
    return planets.filter(planet => planet.size > 100000)
}

class Planets extends Presenter {
  getModel() {
    return {
      bigPlanets: this.repo.observe('planets', getBigPlanets)
    }
  } 
}

This has a few advantages:

  • Subscriptions can be batched together using the CompareTree
  • We could tag handlers just like actions, creating a memoization across multiple presenters. If two presenters have the exact same data dependency, they receive the exact same result
  • It's nicer than state => state.planets, and this new method is absolutely faster than dirty checking state and calling every single function callback.

Long term, I could see a breaking change to Presenters where we add repo as the first argument:

class PlanetPage extends Presenter {
  getModel(repo, props) {
    return {
      planet: repo.observe(`planets.${props.id}`)
    }
  } 
}

DOM.render(<PlanetPage planet="earth"/>, el)

I really dig this. Is that repo.on('change:?key') syntax inspired by Backbone by any chance? 😉
Also the processing function as the second argument could also be super nice!

Is that repo.on('change:?key') syntax inspired by Backbone by any chance

It is! This is actually possible right now using repo.on. You can see this in our canvas example:

https://github.com/vigetlabs/microcosm/blob/master/examples/canvas/app/boot.js#L42-L44

This is no longer necessary now! Domains are observables, so you can do:

repo.domains.thing.subscribe(next => doSomething(next))

Long term, I think we could add a method to our observable implementation to pluck out a specific value given a key path. I'll write up some notes for that.