Skip to content

Commit

Permalink
Merge pull request #4476 from reduxjs/feature/listeners-map
Browse files Browse the repository at this point in the history
  • Loading branch information
markerikson committed Jan 30, 2023
2 parents 3dd8082 + 1599aad commit bc359c9
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 11 deletions.
23 changes: 13 additions & 10 deletions src/createStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import {
StoreEnhancer,
Dispatch,
Observer,
ExtendState
ExtendState,
ListenerCallback
} from './types/store'
import { Action } from './types/actions'
import { Reducer } from './types/reducers'
Expand Down Expand Up @@ -119,8 +120,9 @@ export function createStore<S, A extends Action, Ext = {}, StateExt = never>(

let currentReducer = reducer
let currentState = preloadedState as S
let currentListeners: (() => void)[] | null = []
let currentListeners: Map<number, ListenerCallback> | null = new Map()
let nextListeners = currentListeners
let listenerIdCounter = 0
let isDispatching = false

/**
Expand All @@ -132,7 +134,10 @@ export function createStore<S, A extends Action, Ext = {}, StateExt = never>(
*/
function ensureCanMutateNextListeners() {
if (nextListeners === currentListeners) {
nextListeners = currentListeners.slice()
nextListeners = new Map()
currentListeners.forEach((listener, key) => {
nextListeners.set(key, listener)
})
}
}

Expand Down Expand Up @@ -197,7 +202,8 @@ export function createStore<S, A extends Action, Ext = {}, StateExt = never>(
let isSubscribed = true

ensureCanMutateNextListeners()
nextListeners.push(listener)
const listenerId = listenerIdCounter++
nextListeners.set(listenerId, listener)

return function unsubscribe() {
if (!isSubscribed) {
Expand All @@ -214,8 +220,7 @@ export function createStore<S, A extends Action, Ext = {}, StateExt = never>(
isSubscribed = false

ensureCanMutateNextListeners()
const index = nextListeners.indexOf(listener)
nextListeners.splice(index, 1)
nextListeners.delete(listenerId)
currentListeners = null
}
}
Expand Down Expand Up @@ -272,11 +277,9 @@ export function createStore<S, A extends Action, Ext = {}, StateExt = never>(
}

const listeners = (currentListeners = nextListeners)
for (let i = 0; i < listeners.length; i++) {
const listener = listeners[i]
listeners.forEach(listener => {
listener()
}

})
return action
}

Expand Down
4 changes: 3 additions & 1 deletion src/types/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ export interface Unsubscribe {
(): void
}

export type ListenerCallback = () => void

declare global {
interface SymbolConstructor {
readonly observable: symbol
Expand Down Expand Up @@ -198,7 +200,7 @@ export interface Store<
* @param listener A callback to be invoked on every dispatch.
* @returns A function to remove this change listener.
*/
subscribe(listener: () => void): Unsubscribe
subscribe(listener: ListenerCallback): Unsubscribe

/**
* Replaces the reducer currently used by the store to calculate the state.
Expand Down

0 comments on commit bc359c9

Please sign in to comment.