Skip to content

Commit 32481c9

Browse files
committed
combine the idea used in reduxjs#1505
1 parent 76a1d08 commit 32481c9

File tree

1 file changed

+28
-56
lines changed

1 file changed

+28
-56
lines changed

src/hooks/useSelector.js

Lines changed: 28 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useState, useEffect, useMemo, useContext } from 'react'
1+
import { useReducer, useEffect, useMemo, useContext } from 'react'
22
import { useReduxContext as useDefaultReduxContext } from './useReduxContext'
33
import Subscription from '../utils/Subscription'
44
import { ReactReduxContext } from '../components/Context'
@@ -11,72 +11,44 @@ function useSelectorWithStoreAndSubscription(
1111
store,
1212
contextSub
1313
) {
14-
const [state, setState] = useState(() => ({
15-
storeState: store.getState(),
16-
selector,
17-
selectedState: selector(store.getState())
18-
// subscriptionCallbackError: undefined
19-
}))
14+
const [state, dispatch] = useReducer(
15+
(prevState, storeState) => {
16+
const nextSelectedState = selector(storeState)
17+
if (equalityFn(nextSelectedState, prevState.selectedState)) {
18+
// bail out
19+
return prevState
20+
}
21+
return {
22+
selector,
23+
storeState,
24+
selectedState: nextSelectedState
25+
}
26+
},
27+
store.getState(),
28+
storeState => ({
29+
selector,
30+
storeState,
31+
selectedState: selector(storeState)
32+
})
33+
)
2034

2135
const subscription = useMemo(() => new Subscription(store, contextSub), [
2236
store,
2337
contextSub
2438
])
2539

2640
let selectedState = state.selectedState
27-
28-
try {
29-
if (selector !== state.selector || state.subscriptionCallbackError) {
30-
const newSelectedState = selector(state.storeState)
31-
if (!equalityFn(newSelectedState, selectedState)) {
32-
selectedState = newSelectedState
33-
// schedule another update
34-
setState(prevState => ({
35-
...prevState,
36-
selector,
37-
selectedState
38-
// subscriptionCallbackError: undefined
39-
}))
40-
}
41-
}
42-
} catch (err) {
43-
if (state.subscriptionCallbackError) {
44-
err.message += `\nThe error may be correlated with this previous error:\n${state.subscriptionCallbackError.stack}\n\n`
41+
if (state.selector !== selector) {
42+
const nextSelectedState = selector(state.storeState)
43+
if (!equalityFn(nextSelectedState, state.selectedState)) {
44+
selectedState = nextSelectedState
45+
// schedule another update
46+
dispatch(state.storeState)
4547
}
46-
47-
throw err
4848
}
4949

5050
useEffect(() => {
51-
function checkForUpdates() {
52-
const newStoreState = store.getState()
53-
setState(prevState => {
54-
let newSelectedState
55-
let subscriptionCallbackError
56-
try {
57-
newSelectedState = prevState.selector(newStoreState)
58-
59-
if (equalityFn(newSelectedState, prevState.selectedState)) {
60-
// bail out rendering
61-
return prevState
62-
}
63-
} catch (err) {
64-
// we ignore all errors here, since when the component
65-
// is re-rendered, the selectors are called again, and
66-
// will throw again, if neither props nor store state
67-
// changed
68-
subscriptionCallbackError = err
69-
}
70-
71-
return {
72-
...prevState,
73-
storeState: newStoreState,
74-
selectedState: newSelectedState,
75-
subscriptionCallbackError
76-
}
77-
})
78-
}
79-
51+
const checkForUpdates = () => dispatch(store.getState())
8052
subscription.onStateChange = checkForUpdates
8153
subscription.trySubscribe()
8254

0 commit comments

Comments
 (0)