Last active
August 29, 2015 14:20
-
-
Save goatslacker/a8dc917b8a7700597478 to your computer and use it in GitHub Desktop.
Nuclear-style transforms for Alt stores
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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