Skip to content

Conversation

nhunzaker
Copy link
Contributor

@nhunzaker nhunzaker commented Sep 7, 2016

I want to better support custom APIs for Stores and the use of complex data libraries such as ImmutableJS. To do that, stores need to be more powerful:

class ImmutableStore extends Store {

  getInitialState() {
    return Immutable.Map()
  }

  shouldCommit(next, previous) {
    return Immutable.is(next, previous) === false
  }

  add(state, record) {
    return state.set(record.id, record)
  }

  remove(state, id) {
    return state.remove(id)
  }

  commit(state) {
    return Array.from(state.values())
  }

  register() {
    return {
      [create]  : this.add,
      [destroy] : this.remove
    }
  }
}

What's new:

This PR adds several new options to stores:

setup - A one time preparation method called right after a store is added
set - How should a store assign a value?
commit - How should a store expose a value publicly?

Three state phases

State is captured in three phases. Each stage solves a different problem:

  1. archive - A cache of completed actions. Since actions will never change, writing them to an archive allows the actions to be disposed, improving dispatch efficiency.
  2. staged - The "private" state, before writing for public consumption. Store may not operate on primitive (like ImmutableJS), this allows a store to work with complex data types while still exposing a primitive public state.
  3. state -  Public state. The willCommit lifecycle method allows a store to transform private state before it changes. This is useful for turning something like Immutable.Map() or a linked-list into a primitive object or array.

Pure mode

Additionally microcosm can be pure mode, similarly to the Presenter. In this case, it will only assign a new state if is not shallowly equal.

I wrote up a few exploratory test cases. I might move them to the examples folder if it seems prudent. They don't necessarily have to be in the standard test suite.

Outstanding ideas

What do you think about:

  1. Presenter "pure" mode should be inherited by it's associated Microcosm. It's still overridable as a prop.
  2. Each store has a shouldCommit hook. Technically we don't even have to shallowEquals, we could just increment a revision number. We could even do this on a store-by-store level.
  3. Stores can be classes now. This means they can have their own internal state. What do we think about that?
  4. I don't feel 100% on these names, or that they are concise, and easy to accidentally override. Should we make them intentionally more verbose?

@coveralls
Copy link

Coverage Status

Coverage remained the same at 100.0% when pulling 1374e1b on nh-power-stores into 933c10e on master.

@coveralls
Copy link

Coverage Status

Coverage remained the same at 100.0% when pulling ae115aa on nh-power-stores into 933c10e on master.

@coveralls
Copy link

Coverage Status

Coverage remained the same at 100.0% when pulling b2344fa on nh-power-stores into 933c10e on master.

@coveralls
Copy link

Coverage Status

Coverage remained the same at 100.0% when pulling 28f9981 on nh-power-stores into 933c10e on master.


const next = this.stores.reduce((memo, store) => {
return this.commit(memo, store[0], store[1])
}, merge({}, staged))
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like this. This is inefficiency (though not much). I don't like shallow copying the staged changes, and I don't like the anonymous function call. I also don't like the [key, value] tuple.

Something to muse on...

@nhunzaker nhunzaker merged commit 28f9981 into master Sep 8, 2016
@nhunzaker nhunzaker deleted the nh-power-stores branch September 9, 2016 11:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants