Skip to content

Instantly share code, notes, and snippets.

@goatslacker
Last active August 29, 2015 14:20
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save goatslacker/a8dc917b8a7700597478 to your computer and use it in GitHub Desktop.
Save goatslacker/a8dc917b8a7700597478 to your computer and use it in GitHub Desktop.
Nuclear-style transforms for Alt stores
import Alt from './'
// the magic sauce
import { createTransform } from './utils/frp'
// decorator utilities
import { createStore, bind } from './utils/decorators'
const alt = new Alt()
// create a transform function
// we pass in alt so we get access to the dispatcher
const transform = createTransform(alt)
// creating some actions
// nothing special to see here
const addItem = alt.createAction('addItem', function (item) {
this.dispatch(item)
})
const taxPercentChanged = alt.createAction('taxPercentChanged', function (item) {
this.dispatch(item)
})
const shared = alt.createAction('shared', function () { this.dispatch() })
// two stores
// an item store and a tax store
@createStore(alt)
class ItemStore {
constructor() {
this.items = []
}
@bind(addItem)
addItem(item) {
this.items.push(item)
}
@bind(shared)
test() { }
}
@createStore(alt)
class TaxStore {
constructor() {
this.taxPercent = 0
}
@bind(taxPercentChanged)
setTaxPercent(tax) {
this.taxPercent = tax
}
@bind(shared)
test() { }
}
// here comes the interesting part
// we create these subscriptions which transform state when it is updated.
// transform takes many parameters: the first is the transforming function and any subsequent parameters
// correspond to the stores and/or subscriptions we want to listen in on.
// these in turn are passed as arguments to the transforming function.
// the API for these objects is { subscribe(onChange: function): { dispose: function } }
// in this particular case we're listening in on the ItemStore and we get the state passed in
const subtotalGetter = transform((state) => {
return state.items.reduce(
(total, item) => total + (item.price * item.quantity), 0
)
}, ItemStore)
// here we listen in on the previous subtotal subscription as well as the TaxStore.
// { taxPercent } is destructured from TaxStore.getState() and subtotal is the value that is produced above.
const taxesGetter = transform((subtotal, { taxPercent }) => {
return subtotal * (taxPercent / 100)
}, subtotalGetter, TaxStore)
// this transform listens in on the previous two
const totalGetter = transform((subtotal, tax) => {
return subtotal + tax
}, subtotalGetter, taxesGetter)
// finally we can subscribe to any of these but we'll just subscribe to the last one to get the value
totalGetter.subscribe(value => console.log('CHANGED', value))
// call the actions
addItem({ name: 'Soap', price: 5, quantity: 2 }) // 10
taxPercentChanged(10) // 11
shared() // 11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment