@@ -3,12 +3,15 @@ import React, {
3
3
createContext ,
4
4
useCallback ,
5
5
useContext ,
6
+ useEffect ,
6
7
useLayoutEffect ,
7
8
useMemo ,
8
9
useRef ,
10
+ useState ,
9
11
createMutableSource ,
10
12
useMutableSource ,
11
13
} from 'react' ;
14
+ import { unstable_batchedUpdates as batchedUpdates } from 'react-dom' ;
12
15
import { createStore } from 'redux' ;
13
16
14
17
import {
@@ -20,10 +23,34 @@ import {
20
23
} from '../common' ;
21
24
22
25
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
+ } ;
24
34
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
+ } ) ;
25
52
const contextValue = useMemo ( ( ) => ( {
26
- source : createMutableSource ( store , ( ) => store . getState ( ) ) ,
53
+ source : createMutableSource ( { storeStateRef , subscribersRef } , ( ) => storeStateRef . current ) ,
27
54
dispatch : store . dispatch ,
28
55
} ) , [ store ] ) ;
29
56
return (
@@ -38,8 +65,11 @@ const useSelector = (selector) => {
38
65
useLayoutEffect ( ( ) => {
39
66
selectorRef . current = selector ;
40
67
} ) ;
41
- const getSnapshot = useCallback ( ( store ) => selectorRef . current ( store . getState ( ) ) , [ ] ) ;
42
68
const { source } = useContext ( StoreContext ) ;
69
+ const getSnapshot = useCallback (
70
+ ( { storeStateRef } ) => selectorRef . current ( storeStateRef . current ) ,
71
+ [ ] ,
72
+ ) ;
43
73
return useMutableSource ( source , getSnapshot , subscribe ) ;
44
74
} ;
45
75
0 commit comments