Skip to content
Prev Previous commit
Update to fix edge cases of unwatch fn
  • Loading branch information
jordangarcia committed Nov 3, 2015
commit f712e7d13df0207bcdf1012ebd3b893e832f5fa2
18 changes: 10 additions & 8 deletions src/reactor.js
Original file line number Diff line number Diff line change
Expand Up @@ -201,10 +201,9 @@ class Reactor {

dirtyStores.forEach(id => {
const entries = this.observerState.getIn(['stores', id])
if (!entries) {
return
if (entries) {
set.union(entries)
}
set.union(entries)
})
})

Expand All @@ -219,11 +218,14 @@ class Reactor {
const currValue = currEvaluateResult.result

if (!Immutable.is(prevValue, currValue)) {
const handlers = this.observerState.getIn(['gettersMap', getter])
.map(observerId => this.observerState.getIn(['observersMap', observerId, 'handler']))
// don't notify here in the case a handler called unobserve on another observer

handlers.forEach(handler => handler.call(null, currValue))
const observerIds = this.observerState.getIn(['gettersMap', getter], [])
observerIds.forEach(observerId => {
const handler = this.observerState.getIn(['observersMap', observerId, 'handler'])
// don't notify here in the case a handler called unobserve on another observer
if (handler) {
handler.call(null, currValue)
}
})
}
})

Expand Down
25 changes: 17 additions & 8 deletions src/reactor/fns.js
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,6 @@ exports.addObserver = function(observerState, getter, handler) {

if (storeDeps.size === 0) {
// no storeDeps means the observer is dependent on any of the state changing

updatedObserverState = updatedObserverState.updateIn(['any'], getters => getters.add(getter))
} else {
updatedObserverState = updatedObserverState.withMutations(map => {
Expand Down Expand Up @@ -246,24 +245,34 @@ exports.removeObserverByEntry = function(observerState, entry) {
const getter = entry.get('getter')
const storeDeps = entry.get('storeDeps')

map.updateIn(['gettersMap', getter], observerIds => observerIds.remove(id));

if (map.getIn(['gettersMap', getter]).size <= 0) {
const observerIds = map.getIn(['gettersMap', getter])
if (!observerIds) {
// getter doesn't exist if reactor.reset() is called before the unwatchFn()
return
}
const updatedObserverIds = observerIds.remove(id)
map.setIn(['gettersMap', getter], updatedObserverIds)

if (updatedObserverIds.size === 0) {
// all observers have been removed for this getter, remove other entries
if (storeDeps.size === 0) {
// no storeDeps means the observer is dependent on any of the state changing
map.update('any', getters => getters.remove(getter));
} else {
storeDeps.forEach(storeId => {
map.updateIn(['stores', storeId]
, getters => getters.remove(getter) )
map.updateIn(['stores', storeId], getters => {
if (getters) {
// check to make sure the getters Set exists for this store,
// in the case of reactor.reset() is called before the unwatchFn()
return getters.remove(getter)
}
return getters
})
})
}

}

map.removeIn(['observersMap', id])

})
}

Expand Down