Skip to content

Commit

Permalink
resolves woltapp#1
Browse files Browse the repository at this point in the history
Create collection and withCollection HOCs to allow global reload
  • Loading branch information
Goues committed Jan 3, 2018
1 parent 292a323 commit e8c6aaa
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 0 deletions.
21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,27 @@ const ConnectedComponent = reduxAutoloader({
})(ExampleComponent);
```

#### Reload (refresh) all active loaders

To create a "refresh all" button, simply use `collection` HOC instead of `reduxAutoloader` one. It has the same signature.

```jsx
import { collectionfrom 'redux-autoloader';

const ConnectedComponent = collection(options)(ExampleComponent);
```

Then you can create a refresh button like using `withCollection` that passes a global `.refresh()` method as a prop.

```jsx
import { withCollectionfrom 'redux-autoloader';

const ExampleComponent = ({ refresh }) => {
return <button onClick={refresh} />Reload</button>;
};

const ReloadComoponent = withCollection(ExampleComponent);
```

## API Documentation

Expand Down
74 changes: 74 additions & 0 deletions src/collection.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/* eslint-disable react/no-unused-prop-types,
react/prefer-stateless-function,
react/forbid-prop-types
*/
import { PureComponent, createElement } from 'react';
import PropTypes from 'prop-types';
import getDisplayName from 'react-display-name';
import reduxAutoloader from './reduxAutoloader';

import { assert } from './utils';

const hashTable = {};

export const collection = (options, mapStateToProps) => {
const name = options.name;

assert(name, 'name is required');
assert(typeof name === 'function' || typeof name === 'string', 'name must be a function or a string');

const getReducerName = typeof name === 'function' ? name : () => name;

return (WrappedComponent) => {
class CollectionComponent extends PureComponent {
static propTypes = {
$refresh: PropTypes.func.isRequired,
$name: PropTypes.string.isRequired,
};

componentDidMount() {
hashTable[this.props.$name] = this.props.$refresh;
}

componentWillReceiveProps(nextProps) {
if (nextProps.$refresh !== this.props.$refresh) {
if (this.props.$name !== nextProps.$name) {
delete hashTable[this.props.$name];
}

hashTable[nextProps.$name] = nextProps.$refresh;
}
}

componentWillUnmount() {
delete hashTable[this.props.$name];
}

render() {
const { $name, $refresh, ...props } = this.props; // eslint-disable-line no-unused-vars
return createElement(WrappedComponent, props);
}
}

CollectionComponent.displayName = `collection-${getDisplayName(WrappedComponent)}`;
CollectionComponent.WrappedComponent = WrappedComponent;

return reduxAutoloader(options, (state, props) => ({
$name: getReducerName(props),
$refresh: state.refresh,
...mapStateToProps(state),
}))(CollectionComponent);
};
};

const refresh = () => {
Object.values(hashTable).forEach(loader => loader());
};

export const withCollection = (WrappedComponent) => {
const WithCollection = props => createElement(WrappedComponent, { ...props, refresh });

WithCollection.displayName = `withCollection-${getDisplayName(WrappedComponent)}`;

return WithCollection;
};
1 change: 1 addition & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ export reducer from './reducer';
export * from './selectors';
export * from './actions';
export reduxAutoloader from './reduxAutoloader';
export * from './collection';

0 comments on commit e8c6aaa

Please sign in to comment.