Skip to content

Commit 13a1f8c

Browse files
committed
feat(refs): unbind refs when parent is unbound
1 parent c2b8991 commit 13a1f8c

File tree

2 files changed

+54
-9
lines changed

2 files changed

+54
-9
lines changed

src/index.js

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ function updateDataFromDocumentSnapshot ({ snapshot, obj, key, subs, depth = 0,
5959
obj: obj[key],
6060
key: refKey,
6161
depth: depth + 1,
62+
// TODO parentSubs
6263
resolve
6364
}),
6465
path: ref.path
@@ -76,7 +77,14 @@ function subscribeToDocument ({ ref, obj, key, depth, resolve }) {
7677
const subs = Object.create(null)
7778
return ref.onSnapshot(doc => {
7879
if (doc.exists) {
79-
updateDataFromDocumentSnapshot({ snapshot: createSnapshot(doc), obj, key, subs, depth, resolve })
80+
updateDataFromDocumentSnapshot({
81+
snapshot: createSnapshot(doc),
82+
obj,
83+
key,
84+
subs,
85+
depth,
86+
resolve
87+
})
8088
} else {
8189
obj[key] = null
8290
resolve()
@@ -98,7 +106,7 @@ function bindDocument ({
98106
// bind here the function so it can be resolve anywhere
99107
// this is specially useful for refs
100108
resolve = callOnceWithArg(resolve, () => vm[key])
101-
return document.onSnapshot(doc => {
109+
const unbind = document.onSnapshot(doc => {
102110
if (doc.exists) {
103111
updateDataFromDocumentSnapshot({
104112
snapshot: createSnapshot(doc),
@@ -110,10 +118,16 @@ function bindDocument ({
110118
} else {
111119
resolve()
112120
}
113-
// TODO resolve when does not exist ?
114121
}, reject)
115122

116123
// TODO return a custom unbind function that unbind all refs
124+
return () => {
125+
unbind()
126+
for (const subKey in subs) {
127+
const sub = subs[subKey]
128+
sub.unbind()
129+
}
130+
}
117131
}
118132

119133
function bind ({ vm, key, ref }) {

test/refs.spec.js

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ beforeEach(async () => {
1515
b = db.collection().doc()
1616
c = collection.doc()
1717
d = collection.doc()
18-
await c.update({ foo: 'foo' })
18+
await c.update({ c: true })
1919
await d.update({ ref: c })
2020

2121
vm = new Vue({
@@ -63,15 +63,15 @@ test('binds refs on documents', async () => {
6363
test('update inner ref', async () => {
6464
expect(vm.d).toEqual({
6565
ref: {
66-
foo: 'foo'
66+
c: true
6767
}
6868
})
6969

70-
await c.update({ foo: 'bar' })
70+
await c.update({ c: false })
7171

7272
expect(vm.d).toEqual({
7373
ref: {
74-
foo: 'bar'
74+
c: false
7575
}
7676
})
7777
})
@@ -95,8 +95,7 @@ test('unbinds previously bound document when overwriting a bound', async () => {
9595
c.onSnapshot = jest.fn(fn => onSnapshot((...args) => {
9696
spy()
9797
fn(...args)
98-
})
99-
)
98+
}))
10099
await c.update({ baz: 'baz' })
101100
await d.update({ ref: c })
102101
await delay(5)
@@ -155,3 +154,35 @@ test('resolves the promise when the document does not exist', async () => {
155154
await vm.$bind('item', a)
156155
expect(vm.item).toBe(null)
157156
})
157+
158+
function spyUnbind (ref) {
159+
const spy = jest.fn()
160+
const onSnapshot = ref.onSnapshot.bind(ref)
161+
ref.onSnapshot = jest.fn(fn => {
162+
const unbind = onSnapshot(fn)
163+
return () => {
164+
spy()
165+
unbind()
166+
}
167+
})
168+
return spy
169+
}
170+
171+
test('unbinds all refs when the document is unbound', async () => {
172+
const cSpy = spyUnbind(c)
173+
const dSpy = spyUnbind(d)
174+
// rebind to use the spies
175+
await vm.$bind('d', d)
176+
expect(vm.d).toEqual({
177+
ref: {
178+
c: true
179+
}
180+
})
181+
vm.$unbind('d')
182+
183+
expect(dSpy.mock.calls.length).toBe(1)
184+
expect(cSpy.mock.calls.length).toBe(1)
185+
186+
cSpy.mockRestore()
187+
dSpy.mockRestore()
188+
})

0 commit comments

Comments
 (0)