choo: fix subs

This commit is contained in:
Yoshua Wuyts
2016-05-16 04:09:02 +07:00
parent 8531bb4357
commit e8f327dbb0
+67 -63
View File
@@ -15,7 +15,7 @@ function choo (opts) {
opts = opts || {} opts = opts || {}
const name = opts.name || 'choo' const name = opts.name || 'choo'
var _router = null var _router = null
var _models = [ appInit() ] var _models = [ appInit(opts) ]
start.router = router start.router = router
start.model = model start.model = model
@@ -26,30 +26,58 @@ function choo (opts) {
// start the application // start the application
// null -> DOMNode // null -> DOMNode
function start () { function start () {
const events = bootstrap(_models) const initialState = {}
const send = sendAction({ const reducers = {}
onaction: events.handleAction, const effects = {}
onchange: onchange,
state: events.state _models.forEach(function (model) {
if (model.state) apply(model.name, model.state, initialState)
if (model.reducers) apply(model.name, model.reducers, reducers)
if (model.effects) apply(model.name, model.effects, effects)
}) })
if (opts.href !== false) { const send = sendAction({
href(function (href) { onaction: handleAction,
send('location', { location: href }) onchange: onchange,
}) state: initialState
} })
if (opts.history !== false) { _models.forEach(function (model) {
history(function (href) { if (model.subscriptions) {
send('location', { location: href }) model.subscriptions.forEach(function (sub) {
}) sub(send)
} })
}
})
const rootId = name + '-root' const rootId = name + '-root'
const tree = _router(send.state().location, send.state(), send) const tree = _router(send.state().location, send.state(), send)
tree.setAttribute('id', rootId) tree.setAttribute('id', rootId)
return tree return tree
function handleAction (action, state, send) {
var _reducers = false
var _effects = false
var newState = null
if (reducers[action.type]) {
newState = xtend(state, reducers[action.type](action, state))
_reducers = true
}
if (effects[action.type]) {
effects[action.type](action, newState || state, send)
newState = newState || state
_effects = true
}
if (!_reducers && !_effects) {
throw new Error('Could not find action ' + action.type)
}
return newState
}
// update on every change // update on every change
function onchange (action, state) { function onchange (action, state) {
const oldTree = document.querySelector('#' + rootId) const oldTree = document.querySelector('#' + rootId)
@@ -76,17 +104,36 @@ function choo (opts) {
} }
// initial application state model // initial application state model
// null -> obj // obj -> obj
function appInit () { function appInit (opts) {
return { const model = {
state: { state: {
location: document.location.href location: document.location.href
}, },
reducers: { reducers: {
location: setLocation location: setLocation
} },
subscriptions: []
} }
if (opts.href !== false) {
model.subscriptions.push(function (send) {
href(function (href) {
send('location', { location: href })
})
})
}
if (opts.history !== false) {
model.subscriptions.push(function (send) {
history(function (href) {
send('location', { location: href })
})
})
}
return model
// handle href links // handle href links
function setLocation (action, state) { function setLocation (action, state) {
const location = action.location.replace(/#.*/, '') const location = action.location.replace(/#.*/, '')
@@ -94,49 +141,6 @@ function appInit () {
} }
} }
function bootstrap (events) {
const initialState = {}
const reducers = {}
const effects = {}
events.forEach(function (model) {
if (model.state) apply(model.name, model.state, initialState)
if (model.reducers) apply(model.name, model.reducers, reducers)
if (model.effects) apply(model.name, model.effects, effects)
if (model.subscriptions) {
apply(model.name, model.subscriptions, initialState)
}
})
return {
handleAction: handleAction,
state: initialState
}
function handleAction (action, state, send) {
var _reducers = false
var _effects = false
var newState = null
if (reducers[action.type]) {
newState = xtend(state, reducers[action.type](action, state))
_reducers = true
}
if (effects[action.type]) {
effects[action.type](action, newState || state, send)
newState = newState || state
_effects = true
}
if (!_reducers && !_effects) {
throw new Error('Could not find action ' + action.type)
}
return newState
}
}
// compose an object conditionally // compose an object conditionally
// (str, obj, obj) -> null // (str, obj, obj) -> null
function apply (name, source, target) { function apply (name, source, target) {