Skip to content

Commit ff9957b

Browse files
committed
idea: fingerprint to sort subscriptions (#22)
1 parent 43f0bb0 commit ff9957b

File tree

2 files changed

+32
-3
lines changed

2 files changed

+32
-3
lines changed

src/provider.js

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,43 @@ export const ReduxStoreContext = createContext(warningObject);
1515

1616
// patch store with batchedUpdates
1717
const patchReduxStore = (origStore) => {
18-
if (!batchedUpdates) return origStore;
18+
const safeBatchedUpdates = batchedUpdates || (f => f());
1919
const listeners = [];
20+
// proof of concept: heuristically reorder listeners to mimic top-down
21+
const fingerprints = [];
22+
const registerFingerprint = (fingerprint) => {
23+
const index = fingerprints.indexOf(fingerprint);
24+
if (index < 0) fingerprints.push(fingerprint);
25+
};
26+
const unregisterFingerprint = (fingerprint) => {
27+
const index = fingerprints.indexOf(fingerprint);
28+
if (index >= 0) fingerprints.splice(index, 1);
29+
};
30+
const sortListeners = () => {
31+
listeners.sort((a, b) => {
32+
const ia = fingerprints.indexOf(a.fingerprint);
33+
const ib = fingerprints.indexOf(b.fingerprint);
34+
return ia - ib;
35+
});
36+
};
2037
let unsubscribe;
2138
const subscribe = (listener) => {
2239
listeners.push(listener);
2340
if (listeners.length === 1) {
2441
unsubscribe = origStore.subscribe(() => {
25-
batchedUpdates(() => {
42+
if (fingerprints.length) {
43+
sortListeners();
44+
// we can't use batchedUpdates because we need to render each time
2645
listeners.forEach(l => l());
27-
});
46+
} else {
47+
safeBatchedUpdates(() => {
48+
listeners.forEach(l => l());
49+
});
50+
}
2851
});
2952
}
3053
return () => {
54+
unregisterFingerprint(listener.fingerprint);
3155
const index = listeners.indexOf(listener);
3256
listeners.splice(index, 1);
3357
if (listeners.length === 0) {
@@ -38,6 +62,7 @@ const patchReduxStore = (origStore) => {
3862
return {
3963
...origStore,
4064
subscribe,
65+
registerFingerprint,
4166
};
4267
};
4368

src/useReduxSelectors.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ export const useReduxSelectors = (selectorMap) => {
6262
useIsomorphicLayoutEffect(() => {
6363
lastTracked.current = { keys, mapped, trapped };
6464
});
65+
// fingerprint
66+
const fingerprint = useRef(Symbol('fingerprint'));
67+
store.registerFingerprint(fingerprint.current);
6568
// subscription
6669
useEffect(() => {
6770
const callback = () => {
@@ -86,6 +89,7 @@ export const useReduxSelectors = (selectorMap) => {
8689
forceUpdate();
8790
}
8891
};
92+
callback.fingerprint = fingerprint.current;
8993
// run once in case the state is already changed
9094
callback();
9195
const unsubscribe = store.subscribe(callback);

0 commit comments

Comments
 (0)