-
Notifications
You must be signed in to change notification settings - Fork 30
/
injectReducer.js
81 lines (69 loc) · 2.05 KB
/
injectReducer.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
import React from 'react';
import hoistNonReactStatics from 'hoist-non-react-statics';
import { useStore, ReactReduxContext } from 'react-redux';
import getInjectors from './reducerInjectors';
/**
* A higher-order component that dynamically injects a reducer when the
* component is instantiated
*
* @param {Object} params
* @param {string} params.key The key to inject the reducer under
* @param {function} params.reducer The reducer that will be injected
*
* @example
*
* class BooksManager extends React.PureComponent {
* render() {
* return null;
* }
* }
*
* export default injectReducer({ key: "books", reducer: booksReducer })(BooksManager)
*
* @public
*/
export default ({ key, reducer }) => WrappedComponent => {
class ReducerInjector extends React.Component {
static WrappedComponent = WrappedComponent;
static contextType = ReactReduxContext;
static displayName = `withReducer(${WrappedComponent.displayName ||
WrappedComponent.name ||
'Component'})`;
constructor(props, context) {
super(props, context);
getInjectors(context.store).injectReducer(key, reducer);
}
render() {
return <WrappedComponent {...this.props} />;
}
}
return hoistNonReactStatics(ReducerInjector, WrappedComponent);
};
/**
* A react hook that dynamically injects a reducer when the hook is run
*
* @param {Object} params
* @param {string} params.key The key to inject the reducer under
* @param {function} params.reducer The reducer that will be injected
*
* @example
*
* function BooksManager() {
* useInjectReducer({ key: "books", reducer: booksReducer })
*
* return null;
* }
*
* @returns {boolean} flag indicating whether or not the reducer has finished injecting
* @public
*/
const useInjectReducer = ({ key, reducer }) => {
const store = useStore();
const [isInjected, setIsInjected] = React.useState(false);
React.useLayoutEffect(() => {
getInjectors(store).injectReducer(key, reducer);
setIsInjected(true);
}, []);
return isInjected;
};
export { useInjectReducer };