File tree 2 files changed +23
-13
lines changed
2 files changed +23
-13
lines changed Original file line number Diff line number Diff line change @@ -4,36 +4,46 @@ import { getBatch } from './batch'
4
4
// well as nesting subscriptions of descendant components, so that we can ensure the
5
5
// ancestor components re-render before descendants
6
6
7
+ const CLEARED = null
7
8
const nullListeners = { notify ( ) { } }
8
9
9
10
function createListenerCollection ( ) {
10
11
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 = [ ]
13
16
14
17
return {
15
18
clear ( ) {
16
- listeners = { }
19
+ next = CLEARED
20
+ current = CLEARED
17
21
} ,
18
22
19
23
notify ( ) {
24
+ const listeners = ( current = next )
20
25
batch ( ( ) => {
21
- for ( const id in listeners ) {
22
- listeners [ id ] ( )
26
+ for ( let i = 0 ; i < listeners . length ; i ++ ) {
27
+ listeners [ i ] ( )
23
28
}
24
29
} )
25
30
} ,
26
31
27
32
get ( ) {
28
- return listeners
33
+ return next
29
34
} ,
30
35
31
36
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 )
34
40
35
41
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 )
37
47
}
38
48
}
39
49
}
Original file line number Diff line number Diff line change @@ -97,11 +97,11 @@ describe('React', () => {
97
97
</ ProviderMock >
98
98
)
99
99
100
- expect ( Object . keys ( rootSubscription . listeners . get ( ) ) . length ) . toBe ( 1 )
100
+ expect ( rootSubscription . listeners . get ( ) . length ) . toBe ( 1 )
101
101
102
102
store . dispatch ( { type : '' } )
103
103
104
- expect ( Object . keys ( rootSubscription . listeners . get ( ) ) . length ) . toBe ( 2 )
104
+ expect ( rootSubscription . listeners . get ( ) . length ) . toBe ( 2 )
105
105
} )
106
106
107
107
it ( 'unsubscribes when the component is unmounted' , ( ) => {
@@ -125,11 +125,11 @@ describe('React', () => {
125
125
</ ProviderMock >
126
126
)
127
127
128
- expect ( Object . keys ( rootSubscription . listeners . get ( ) ) . length ) . toBe ( 2 )
128
+ expect ( rootSubscription . listeners . get ( ) . length ) . toBe ( 2 )
129
129
130
130
store . dispatch ( { type : '' } )
131
131
132
- expect ( Object . keys ( rootSubscription . listeners . get ( ) ) . length ) . toBe ( 1 )
132
+ expect ( rootSubscription . listeners . get ( ) . length ) . toBe ( 1 )
133
133
} )
134
134
135
135
it ( 'notices store updates between render and store subscription effect' , ( ) => {
You can’t perform that action at this time.
0 commit comments