Skip to content

Commit cf6b7f3

Browse files
committed
This resolves issue woltapp#1:
Create collection and withCollection HOCs to allow global reload
1 parent 292a323 commit cf6b7f3

File tree

3 files changed

+96
-0
lines changed

3 files changed

+96
-0
lines changed

README.md

+21
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,27 @@ const ConnectedComponent = reduxAutoloader({
131131
})(ExampleComponent);
132132
```
133133

134+
#### Reload (refresh) all active loaders
135+
136+
To create a "refresh all" button, simply use `collection` HOC instead of `reduxAutoloader` one. It has the same signature.
137+
138+
```jsx
139+
import { collectionfrom 'redux-autoloader';
140+
141+
const ConnectedComponent = collection(options)(ExampleComponent);
142+
```
143+
144+
Then you can create a refresh button like using `withCollection` that passes a global `.refresh()` method as a prop.
145+
146+
```jsx
147+
import { withCollectionfrom 'redux-autoloader';
148+
149+
const ExampleComponent = ({ refresh }) => {
150+
return <button onClick={refresh} />Reload</button>;
151+
};
152+
153+
const ReloadComoponent = withCollection(ExampleComponent);
154+
```
134155

135156
## API Documentation
136157

src/collection.js

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/* eslint-disable react/no-unused-prop-types,
2+
react/prefer-stateless-function,
3+
react/forbid-prop-types
4+
*/
5+
import { PureComponent, createElement } from 'react';
6+
import PropTypes from 'prop-types';
7+
import getDisplayName from 'react-display-name';
8+
import reduxAutoloader from './reduxAutoloader';
9+
10+
import { assert } from './utils';
11+
12+
const hashTable = {};
13+
14+
export const collection = (options, mapStateToProps) => {
15+
const name = options.name;
16+
17+
assert(name, 'name is required');
18+
assert(typeof name === 'function' || typeof name === 'string', 'name must be a function or a string');
19+
20+
const getReducerName = typeof name === 'function' ? name : () => name;
21+
22+
return (WrappedComponent) => {
23+
class CollectionComponent extends PureComponent {
24+
static propTypes = {
25+
$refresh: PropTypes.func.isRequired,
26+
$name: PropTypes.string.isRequired,
27+
};
28+
29+
componentDidMount() {
30+
hashTable[this.props.$name] = this.props.$refresh;
31+
}
32+
33+
componentWillReceiveProps(nextProps) {
34+
if (nextProps.$refresh !== this.props.$refresh) {
35+
if (this.props.$name !== nextProps.$name) {
36+
delete hashTable[this.props.$name];
37+
}
38+
39+
hashTable[nextProps.$name] = nextProps.$refresh;
40+
}
41+
}
42+
43+
componentWillUnmount() {
44+
delete hashTable[this.props.$name];
45+
}
46+
47+
render() {
48+
const { $name, $refresh, ...props } = this.props; // eslint-disable-line no-unused-vars
49+
return createElement(WrappedComponent, props);
50+
}
51+
}
52+
53+
CollectionComponent.displayName = `collection-${getDisplayName(WrappedComponent)}`;
54+
CollectionComponent.WrappedComponent = WrappedComponent;
55+
56+
return reduxAutoloader(options, (state, props) => ({
57+
$name: getReducerName(props),
58+
$refresh: state.refresh,
59+
...mapStateToProps(state),
60+
}))(CollectionComponent);
61+
};
62+
};
63+
64+
const refresh = () => {
65+
Object.values(hashTable).forEach(loader => loader());
66+
};
67+
68+
export const withCollection = (WrappedComponent) => {
69+
const WithCollection = props => createElement(WrappedComponent, { ...props, refresh });
70+
71+
WithCollection.displayName = `withCollection-${getDisplayName(WrappedComponent)}`;
72+
73+
return WithCollection;
74+
};

src/index.js

+1
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@ export reducer from './reducer';
33
export * from './selectors';
44
export * from './actions';
55
export reduxAutoloader from './reduxAutoloader';
6+
export * from './collection';

0 commit comments

Comments
 (0)