1
- import { useReducer , useRef , useEffect , useMemo , useLayoutEffect } from 'react'
1
+ import { useState , useRef , useEffect , useMemo , useLayoutEffect } from 'react'
2
2
import invariant from 'invariant'
3
3
import { useReduxContext } from './useReduxContext'
4
4
import shallowEqual from '../utils/shallowEqual'
@@ -42,61 +42,46 @@ export function useSelector(selector) {
42
42
invariant ( selector , `You must pass a selector to useSelectors` )
43
43
44
44
const { store, subscription : contextSub } = useReduxContext ( )
45
- const [ , forceRender ] = useReducer ( s => s + 1 , 0 )
46
45
47
46
const subscription = useMemo ( ( ) => new Subscription ( store , contextSub ) , [
48
47
store ,
49
48
contextSub
50
49
] )
51
50
52
- const latestSubscriptionCallbackError = useRef ( )
53
- const latestSelector = useRef ( selector )
54
-
55
- let selectedState = undefined
56
-
51
+ let state , setState
57
52
try {
58
- selectedState = selector ( store . getState ( ) )
53
+ ; [ state , setState ] = useState ( selector ( store . getState ( ) ) )
59
54
} catch ( err ) {
60
- let errorMessage = `An error occured while selecting the store state: ${
55
+ const errorMessage = `An error occured while selecting the store state: ${
61
56
err . message
62
57
} .`
63
-
64
- if ( latestSubscriptionCallbackError . current ) {
65
- errorMessage += `\nThe error may be correlated with this previous error:\n${
66
- latestSubscriptionCallbackError . current . stack
67
- } \n\nOriginal stack trace:`
68
- }
69
-
70
58
throw new Error ( errorMessage )
71
59
}
60
+ const [ error , setError ] = useState ( null )
72
61
73
- const latestSelectedState = useRef ( selectedState )
62
+ const latestSelector = useRef ( selector )
74
63
75
64
useIsomorphicLayoutEffect ( ( ) => {
76
65
latestSelector . current = selector
77
- latestSelectedState . current = selectedState
78
- latestSubscriptionCallbackError . current = undefined
79
- } )
66
+ setState ( selector ( store . getState ( ) ) )
67
+ } , [ selector ] )
80
68
81
69
useIsomorphicLayoutEffect ( ( ) => {
82
70
function checkForUpdates ( ) {
83
71
try {
84
72
const newSelectedState = latestSelector . current ( store . getState ( ) )
85
73
86
- if ( shallowEqual ( newSelectedState , latestSelectedState . current ) ) {
74
+ if ( shallowEqual ( newSelectedState , state ) ) {
87
75
return
88
76
}
89
-
90
- latestSelectedState . current = newSelectedState
77
+ setState ( newSelectedState )
91
78
} catch ( err ) {
92
79
// we ignore all errors here, since when the component
93
80
// is re-rendered, the selectors are called again, and
94
81
// will throw again, if neither props nor store state
95
82
// changed
96
- latestSubscriptionCallbackError . current = err
83
+ setError ( err )
97
84
}
98
-
99
- forceRender ( { } )
100
85
}
101
86
102
87
subscription . onStateChange = checkForUpdates
@@ -107,5 +92,13 @@ export function useSelector(selector) {
107
92
return ( ) => subscription . tryUnsubscribe ( )
108
93
} , [ store , subscription ] )
109
94
110
- return selectedState
95
+ if ( error ) {
96
+ const errorMessage = `An error occured while selecting the store state: ${
97
+ error . message
98
+ } .\n\nOriginal stack trace:\n${ error . stack } `
99
+
100
+ throw new Error ( errorMessage )
101
+ }
102
+
103
+ return state
111
104
}
0 commit comments