1- import { useReducer , useRef , useEffect , useMemo , useLayoutEffect } from 'react'
1+ import {
2+ useReducer ,
3+ useRef ,
4+ useEffect ,
5+ useMemo ,
6+ useLayoutEffect ,
7+ useContext
8+ } from 'react'
29import invariant from 'invariant'
3- import { useReduxContext } from './useReduxContext'
10+ import { useReduxContext as useDefaultReduxContext } from './useReduxContext'
411import Subscription from '../utils/Subscription'
12+ import { ReactReduxContext } from '../components/Context'
513
614// React currently throws a warning when using useLayoutEffect on the server.
715// To get around it, we can conditionally useEffect on the server (no-op) and
@@ -16,33 +24,12 @@ const useIsomorphicLayoutEffect =
1624
1725const refEquality = ( a , b ) => a === b
1826
19- /**
20- * A hook to access the redux store's state. This hook takes a selector function
21- * as an argument. The selector is called with the store state.
22- *
23- * This hook takes an optional equality comparison function as the second parameter
24- * that allows you to customize the way the selected state is compared to determine
25- * whether the component needs to be re-rendered.
26- *
27- * @param {Function } selector the selector function
28- * @param {Function= } equalityFn the function that will be used to determine equality
29- *
30- * @returns {any } the selected state
31- *
32- * @example
33- *
34- * import React from 'react'
35- * import { useSelector } from 'react-redux'
36- *
37- * export const CounterComponent = () => {
38- * const counter = useSelector(state => state.counter)
39- * return <div>{counter}</div>
40- * }
41- */
42- export function useSelector ( selector , equalityFn = refEquality ) {
43- invariant ( selector , `You must pass a selector to useSelectors` )
44-
45- const { store, subscription : contextSub } = useReduxContext ( )
27+ function useSelectorWithStoreAndSubscription (
28+ selector ,
29+ equalityFn ,
30+ store ,
31+ contextSub
32+ ) {
4633 const [ , forceRender ] = useReducer ( s => s + 1 , 0 )
4734
4835 const subscription = useMemo ( ( ) => new Subscription ( store , contextSub ) , [
@@ -112,3 +99,53 @@ export function useSelector(selector, equalityFn = refEquality) {
11299
113100 return selectedState
114101}
102+
103+ /**
104+ * Hook factory, which creates a `useSelector` hook bound to a given context.
105+ *
106+ * @param {Function } [context=ReactReduxContext] Context passed to your `<Provider>`.
107+ * @returns {Function } A `useSelector` hook bound to the specified context.
108+ */
109+ export function createSelectorHook ( context = ReactReduxContext ) {
110+ const useReduxContext =
111+ context === ReactReduxContext
112+ ? useDefaultReduxContext
113+ : ( ) => useContext ( context )
114+ return function useSelector ( selector , equalityFn = refEquality ) {
115+ invariant ( selector , `You must pass a selector to useSelectors` )
116+
117+ const { store, subscription : contextSub } = useReduxContext ( )
118+
119+ return useSelectorWithStoreAndSubscription (
120+ selector ,
121+ equalityFn ,
122+ store ,
123+ contextSub
124+ )
125+ }
126+ }
127+
128+ /**
129+ * A hook to access the redux store's state. This hook takes a selector function
130+ * as an argument. The selector is called with the store state.
131+ *
132+ * This hook takes an optional equality comparison function as the second parameter
133+ * that allows you to customize the way the selected state is compared to determine
134+ * whether the component needs to be re-rendered.
135+ *
136+ * @param {Function } selector the selector function
137+ * @param {Function= } equalityFn the function that will be used to determine equality
138+ *
139+ * @returns {any } the selected state
140+ *
141+ * @example
142+ *
143+ * import React from 'react'
144+ * import { useSelector } from 'react-redux'
145+ *
146+ * export const CounterComponent = () => {
147+ * const counter = useSelector(state => state.counter)
148+ * return <div>{counter}</div>
149+ * }
150+ */
151+ export const useSelector = createSelectorHook ( )
0 commit comments