Skip to content

Commit b7031ce

Browse files
committed
Add protection against newer unsubscribe removing older listeners
1 parent 11ab454 commit b7031ce

File tree

2 files changed

+22
-4
lines changed

2 files changed

+22
-4
lines changed

src/createStore.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,16 @@ export default function createStore(reducer, initialState) {
5959
*/
6060
function subscribe(listener) {
6161
listeners.push(listener);
62+
var isSubscribed = true;
6263

6364
return function unsubscribe() {
64-
var index = listeners.indexOf(listener);
65-
if (index !== -1) {
66-
listeners.splice(index, 1);
65+
if (!isSubscribed) {
66+
return;
6767
}
68+
69+
isSubscribed = false;
70+
var index = listeners.indexOf(listener);
71+
listeners.splice(index, 1);
6872
};
6973
}
7074

test/createStore.spec.js

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ describe('createStore', () => {
201201
expect(listenerB.calls.length).toBe(2);
202202
});
203203

204-
it('should only remove relevant listener no matter how many times unsubscribe called', () => {
204+
it('should only remove listener once when unsubscribe is called', () => {
205205
const store = createStore(reducers.todos);
206206
const listenerA = expect.createSpy(() => {});
207207
const listenerB = expect.createSpy(() => {});
@@ -217,6 +217,20 @@ describe('createStore', () => {
217217
expect(listenerB.calls.length).toBe(1);
218218
});
219219

220+
it('should only remove relevant listener when unsubscribe is called', () => {
221+
const store = createStore(reducers.todos);
222+
const listener = expect.createSpy(() => {});
223+
224+
store.subscribe(listener);
225+
const unsubscribeSecond = store.subscribe(listener);
226+
227+
unsubscribeSecond();
228+
unsubscribeSecond();
229+
230+
store.dispatch(unknownAction());
231+
expect(listener.calls.length).toBe(1);
232+
});
233+
220234
it('should support removing a subscription within a subscription', () => {
221235
const store = createStore(reducers.todos);
222236
const listenerA = expect.createSpy(() => {});

0 commit comments

Comments
 (0)