Skip to content

Commit 53f4261

Browse files
committed
experimental redux binding with storeState
1 parent 99eea3e commit 53f4261

File tree

1 file changed

+33
-3
lines changed

1 file changed

+33
-3
lines changed

src/redux-use-mutable-source/index.js

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,15 @@ import React, {
33
createContext,
44
useCallback,
55
useContext,
6+
useEffect,
67
useLayoutEffect,
78
useMemo,
89
useRef,
10+
useState,
911
createMutableSource,
1012
useMutableSource,
1113
} from 'react';
14+
import { unstable_batchedUpdates as batchedUpdates } from 'react-dom';
1215
import { createStore } from 'redux';
1316

1417
import {
@@ -20,10 +23,34 @@ import {
2023
} from '../common';
2124

2225
const StoreContext = createContext();
23-
const subscribe = (store, callback) => store.subscribe(callback);
26+
const subscribe = ({ subscribersRef }, callback) => {
27+
const subscribers = subscribersRef.current;
28+
subscribers.push(callback);
29+
return () => {
30+
const index = subscribers.indexOf(callback);
31+
subscribers.splice(index, 1);
32+
};
33+
};
2434
const Provider = ({ store, children }) => {
35+
const [storeState, setStoreState] = useState(store.getState());
36+
useEffect(() => {
37+
const callback = () => {
38+
setStoreState(store.getState());
39+
};
40+
const unsubscribe = store.subscribe(callback);
41+
callback();
42+
return unsubscribe;
43+
}, [store]);
44+
const storeStateRef = useRef(storeState);
45+
const subscribersRef = useRef([]);
46+
useEffect(() => {
47+
batchedUpdates(() => {
48+
storeStateRef.current = storeState;
49+
subscribersRef.current.forEach((callback) => callback());
50+
});
51+
});
2552
const contextValue = useMemo(() => ({
26-
source: createMutableSource(store, () => store.getState()),
53+
source: createMutableSource({ storeStateRef, subscribersRef }, () => storeStateRef.current),
2754
dispatch: store.dispatch,
2855
}), [store]);
2956
return (
@@ -38,8 +65,11 @@ const useSelector = (selector) => {
3865
useLayoutEffect(() => {
3966
selectorRef.current = selector;
4067
});
41-
const getSnapshot = useCallback((store) => selectorRef.current(store.getState()), []);
4268
const { source } = useContext(StoreContext);
69+
const getSnapshot = useCallback(
70+
({ storeStateRef }) => selectorRef.current(storeStateRef.current),
71+
[],
72+
);
4373
return useMutableSource(source, getSnapshot, subscribe);
4474
};
4575

0 commit comments

Comments
 (0)