Skip to content

Commit 7a4557b

Browse files
Revert "fix performance createListenerCollection (#1450)"
This reverts commit 476c0de.
1 parent 476c0de commit 7a4557b

File tree

2 files changed

+23
-13
lines changed

2 files changed

+23
-13
lines changed

src/utils/Subscription.js

+19-9
Original file line numberDiff line numberDiff line change
@@ -4,36 +4,46 @@ import { getBatch } from './batch'
44
// well as nesting subscriptions of descendant components, so that we can ensure the
55
// ancestor components re-render before descendants
66

7+
const CLEARED = null
78
const nullListeners = { notify() {} }
89

910
function createListenerCollection() {
1011
const batch = getBatch()
11-
let listeners = {}
12-
let id = 0
12+
// the current/next pattern is copied from redux's createStore code.
13+
// TODO: refactor+expose that code to be reusable here?
14+
let current = []
15+
let next = []
1316

1417
return {
1518
clear() {
16-
listeners = {}
19+
next = CLEARED
20+
current = CLEARED
1721
},
1822

1923
notify() {
24+
const listeners = (current = next)
2025
batch(() => {
21-
for (const id in listeners) {
22-
listeners[id]()
26+
for (let i = 0; i < listeners.length; i++) {
27+
listeners[i]()
2328
}
2429
})
2530
},
2631

2732
get() {
28-
return listeners
33+
return next
2934
},
3035

3136
subscribe(listener) {
32-
const currentId = id++
33-
listeners[currentId] = listener
37+
let isSubscribed = true
38+
if (next === current) next = current.slice()
39+
next.push(listener)
3440

3541
return function unsubscribe() {
36-
delete listeners[currentId]
42+
if (!isSubscribed || current === CLEARED) return
43+
isSubscribed = false
44+
45+
if (next === current) next = current.slice()
46+
next.splice(next.indexOf(listener), 1)
3747
}
3848
}
3949
}

test/hooks/useSelector.spec.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -97,11 +97,11 @@ describe('React', () => {
9797
</ProviderMock>
9898
)
9999

100-
expect(Object.keys(rootSubscription.listeners.get()).length).toBe(1)
100+
expect(rootSubscription.listeners.get().length).toBe(1)
101101

102102
store.dispatch({ type: '' })
103103

104-
expect(Object.keys(rootSubscription.listeners.get()).length).toBe(2)
104+
expect(rootSubscription.listeners.get().length).toBe(2)
105105
})
106106

107107
it('unsubscribes when the component is unmounted', () => {
@@ -125,11 +125,11 @@ describe('React', () => {
125125
</ProviderMock>
126126
)
127127

128-
expect(Object.keys(rootSubscription.listeners.get()).length).toBe(2)
128+
expect(rootSubscription.listeners.get().length).toBe(2)
129129

130130
store.dispatch({ type: '' })
131131

132-
expect(Object.keys(rootSubscription.listeners.get()).length).toBe(1)
132+
expect(rootSubscription.listeners.get().length).toBe(1)
133133
})
134134

135135
it('notices store updates between render and store subscription effect', () => {

0 commit comments

Comments
 (0)