Skip to content

Instantly share code, notes, and snippets.

@MHerszak
Last active November 2, 2017 23:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save MHerszak/2e3602d1f59019177360a2fa06298b09 to your computer and use it in GitHub Desktop.
Save MHerszak/2e3602d1f59019177360a2fa06298b09 to your computer and use it in GitHub Desktop.
withSubscription2.js
import React, { PureComponent } from 'react';
import errors from 'feathers-errors';
import { withPreloader } from './../../redux/container';
import { APP_REST } from './../../components/constants';
import { setDisplayName } from './utils';
import { forEach, map } from './../../utils';
class BaseType {
constructor(props) {
this.document = props;
}
type(available) {
if (available) {
return available;
}
// console.log('Array.isArray(this.document) => ', Array.isArray(this.document));
return Array.isArray(this.document) ? [] : {};
}
}
export class ArrayStrategy extends BaseType {
constructor(collection) {
super(collection);
this.collection = collection;
}
setService(service) {
this.service = service;
}
created(result) {
return [...this.collection, result];
}
updated(result) {
const mappResults = map(this.collection, (val) => {
if (result._id === val._id) {
return Object.assign({}, val, result);
}
return val;
});
return mappResults;
}
}
export class DocumentStrategy extends BaseType {
constructor(document) {
super(document);
this.document = document;
this.service = {};
}
setService(service) {
this.service = service;
}
created(result) {
this.document = result;
return this.document;
}
patched(result) {
this.document = result;
console.log('patched => ', result);
return this.document;
}
updated(result, state, props) {
console.log('props in docStarget => ', props);
console.log('result in docStarget => ', result);
return result;
}
}
function getStrategy(options = {}) {
return options.strategy || new DocumentStrategy();
}
function withStrategyCallback(callback) {
return function stateFunctionHOC(result) {
return function stateFunction(state, props) {
return {
data: callback.call(this, result, state, props)
};
};
};
}
function withService(callback) {
const handler = withStrategyCallback(callback);
return function getResult(result) {
return handler(result);
};
}
const defaultEventTypes = ['created', 'updated', 'removed', 'patched'];
/**
* This function takes a service name ...
* @param serviceName
* @returns {rc}
*/
export default function withSubscription(serviceName) {
/**
* The service will be plugged into app context.
*/
return function rc(WrappedComponent, options = { key: 'data' }) {
// Set context types
const contextTypes = {
...APP_REST
};
/**
* Context of subscription hoc
*/
@withPreloader(options)
class WithSubscription extends PureComponent {
static contextTypes = contextTypes;
constructor(props, context) {
super(props, context);
//
this.options = options;
// get Events
this.events = defaultEventTypes;
// set Strategy
this.strategy = getStrategy(options);
// set key for state
const key = options.key;
// set State
this.state = {
[key]: props[key],
};
// make sure context exists
const { app } = context;
// Is app actually available?
if (!app) {
throw new errors.NotFound(options.noErrMsg ? null : 'No app attached to WithSubscription HOC!');
}
// ... that takes care of the subscription...
this.service = app.service(serviceName);
//
this.strategy.setService(app.service(serviceName));
}
componentDidMount() {
// register all events and handlers
forEach(this.events, (eventType) => {
// created, updated, patched and removed
this.service.on(eventType, this.handleChange(eventType));
});
}
componentWillUnmount() {
// remove all events
forEach(this.events, (eventType) => {
// created, updated, patched and removed
this.service.removeListener(eventType, this.handleChange(eventType));
});
}
handleChange = (eventType = '') => (result) => {
const handler = withService(this.strategy[eventType]);
// const handler = withService(eventType, this.strategy[eventType]);
//
if (this.component) {
return this.setState(handler(result));
}
};
render() {
// ... and renders the wrapped component with the fresh data!
// Notice that we pass through any additional props
return (
<WrappedComponent
ref={(ref) => { this.component = ref; }}
data={this.state.data}
{...this.props}
/>
);
}
}
WithSubscription.displayName = `WithSubscription(${setDisplayName(WrappedComponent)})`;
return WithSubscription;
};
}
// #1 with options
// const BlogPostWithSubscription = (service = '') = withSubscription(
// BlogPost, {
// updated(service, data) {
// console.log(data);
// }
// }
// );
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment