Skip to content

Commit

Permalink
unsubscribe events from within components
Browse files Browse the repository at this point in the history
  • Loading branch information
estrattonbailey committed Jun 4, 2019
1 parent 9615036 commit 23938f2
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 15 deletions.
36 changes: 26 additions & 10 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,25 @@
import { create } from 'evx'

const isObj = v => typeof v === 'object' && !Array.isArray(v)

const validate = (o, name) => {
if (!isObj(o)) throw name + ' should be an object'
}

// make sure evx and picoapp don't destroy the same events
export function component (create) {
return function initialize (node, context) {
return function initialize (node, ctx) {
let subs = []
return {
unmount: create(node, context),
subs,
unmount: create(node, {
...ctx,
on: (evs, fn) => {
const u = ctx.on(evs, fn)
subs.push(u)
return u
}
}),
node
}
}
Expand All @@ -21,11 +37,11 @@ export function picoapp (components = {}, initialState = {}) {
return evx.getState()
},
add (index) {
if (typeof index !== 'object') console.error(new Error(`picoapp - add should be passed an object of components`))
validate(index, 'components')
Object.assign(components, index)
},
hydrate (data) {
if (typeof data !== 'object') console.error(new Error(`picoapp - hydrate should be passed a state object`))
validate(data, 'state')
return evx.hydrate(data)
},
mount (attrs = 'data-component') {
Expand All @@ -40,17 +56,16 @@ export function picoapp (components = {}, initialState = {}) {
const modules = node.getAttribute(attr).split(/\s/)

for (let m = 0; m < modules.length; m++) {
const component = components[modules[m]]
const comp = components[modules[m]]

if (component) {
if (comp) {
node.removeAttribute(attr) // so can't be bound twice

try {
cache.push(component(node, evx))
cache.push(comp(node, evx))
} catch (e) {
console.groupCollapsed(`🚨 %cpicoapp - ${modules[m]} failed - ${e.message || e}`, 'color: red')
console.error(`🚨 %cpicoapp - ${modules[m]} failed - ${e.message || e}`, 'color: red')
console.error(e)
console.groupEnd()
}
}
}
Expand All @@ -59,10 +74,11 @@ export function picoapp (components = {}, initialState = {}) {
},
unmount () {
for (let i = cache.length - 1; i > -1; i--) {
const { unmount, node } = cache[i]
const { unmount, node, subs } = cache[i]

if (!document.documentElement.contains(node)) {
unmount && unmount(node)
subs.map(u => u())
cache.splice(i, 1)
}
}
Expand Down
6 changes: 3 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
"microbundle": "^0.11.0"
},
"dependencies": {
"evx": "^0.2.0",
"evx": "^1.0.0",
"picostate": "^1.4.0"
}
}
40 changes: 39 additions & 1 deletion test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import test from 'ava'
import { picoapp } from './dist/picoapp.js'
import { picoapp, component } from './dist/picoapp.js'

test('init', t => {
const app = picoapp({ foo: 'foo' }, { bar: true })
Expand All @@ -26,3 +26,41 @@ test('events', t => {
app.emit('a')
app.emit('b')
})
test('mount', t => {
t.plan(1)

const node = {
getAttribute () {
return 'foo'
},
removeAttribute () {}
}

global.document = {
querySelectorAll () {
return [ node ]
},
documentElement: {
contains () {
return false
}
}
}

const app = picoapp({
foo: component((node, ctx) => {
const u = ctx.on('foo', () => {
t.pass()
u() // unsub itself
})
})
}, { bar: true })

app.mount()

app.emit('foo')

app.unmount()

app.emit('foo')
})

0 comments on commit 23938f2

Please sign in to comment.