Skip to content

Instantly share code, notes, and snippets.

@jmaguirrei
Last active July 18, 2018 11:28
Show Gist options
  • Save jmaguirrei/5f48a0087f1e391ef81d01ceed6a8c39 to your computer and use it in GitHub Desktop.
Save jmaguirrei/5f48a0087f1e391ef81d01ceed6a8c39 to your computer and use it in GitHub Desktop.
Example of a function that creates a hoc (Higher order component)
import { createChecksStore } from '/imports/common/classes';
import { LocalStoreClass } from '/imports/common/classes'; // SHARED
import { AlertsStore } from './stores/(_Alerts_)/(_Alerts_)';
import { State } from './stores/(_State_)/(_State_)';
import createClocksStore from './stores/(_Clocks_)/(_Clocks_)';
import createSyslidesStore from './stores/(_Syslides_)/(_Syslides_)';
import createMeetingsStore from './stores/((Meetings))/((Meetings))';
import createMembersStore from './stores/((Members))/((Members))';
import createPeopleStore from './stores/((People))/((People))';
import createTopicsStore from './stores/((Topics))/((Topics))';
import createTagsStore from './stores/((Tags))/((Tags))';
import createTransactionsStore from './stores/((Transactions))/((Transactions))';
import createMessagesStore from './stores/((Messages))/((Messages))';
import createPresentationsStore from './stores/((Presentations))/((Presentations))';
import createStreamsStore from './stores/(_Streams_)/(_Streams_)';
import createActionsStore from './stores/((Actions))/((Actions))';
import createAgreementsStore from './stores/((Agreements))/((Agreements))';
import createCommentsStore from './stores/((Comments))/((Comments))';
import createContributionsStore from './stores/((Contributions))/((Contributions))';
import { Settings } from '/imports/common/constants';
import { Link, Router } from '/server/routes';
import createActions from '/module/api/actions';
/* ------------------------------------------------------------------------------------------------
env
------------------------------------------------------------------------------------------------ */
const env = process.env.NODE_ENV;
/* ------------------------------------------------------------------------------------------------
Context
------------------------------------------------------------------------------------------------ */
const TransactionsStore = createTransactionsStore({
State,
});
const PeopleStore = createPeopleStore({
State,
TransactionsStore,
});
const TagsStore = createTagsStore({
State,
});
const MeetingsStore = createMeetingsStore({
State,
PeopleStore,
TagsStore,
});
const PresentationsStore = createPresentationsStore({
State,
PeopleStore,
MeetingsStore,
});
const StreamsStore = createStreamsStore({
State,
});
const ClocksStore = createClocksStore({
State,
MeetingsStore,
StreamsStore,
});
const TopicsStore = createTopicsStore({
State,
MeetingsStore,
AlertsStore,
ClocksStore,
});
const MembersStore = createMembersStore({
State,
MeetingsStore,
PeopleStore,
TopicsStore,
});
const MessagesStore = createMessagesStore({
State,
MeetingsStore,
MembersStore,
TopicsStore,
});
const ActionsStore = createActionsStore({
State,
MeetingsStore,
MembersStore,
ClocksStore,
});
const AgreementsStore = createAgreementsStore({
State,
MeetingsStore,
MembersStore,
ClocksStore,
});
const ContributionsStore = createContributionsStore({
State,
PeopleStore,
MeetingsStore,
});
const SyslidesStore = createSyslidesStore({
State,
StreamsStore,
ClocksStore,
MembersStore,
MeetingsStore,
TopicsStore,
AgreementsStore,
PresentationsStore,
});
const CommentsStore = createCommentsStore({
State,
MeetingsStore,
MembersStore,
});
/* ------------------------------------------------------------------------------------------------
Context
------------------------------------------------------------------------------------------------ */
const ChecksStore = createChecksStore();
const LocalStore = new LocalStoreClass();
const stores = {
ActionsStore,
AgreementsStore,
AlertsStore,
ChecksStore,
ClocksStore,
CommentsStore,
ContributionsStore,
LocalStore,
MeetingsStore,
MembersStore,
MessagesStore,
PeopleStore,
PresentationsStore,
StreamsStore,
SyslidesStore,
TagsStore,
TopicsStore,
TransactionsStore,
};
const Context = {
actions: createActions({ State, Router, ...stores }),
data: stores,
state: State,
utils: {
Router,
Link,
Settings: Settings.public[env],
},
};
export default Context;
import _ from 'lodash';
import React from 'react';
import { computed, toJS } from 'mobx';
import { observer } from 'mobx-react';
/* ------------------------------------------------------------------------------------------------
Some config
------------------------------------------------------------------------------------------------ */
const isBrowser = process.browser;
const isDevelopment = process.env.NODE_ENV === 'development';
const isTest = process.env.NODE_ENV === 'test';
const shouldLog = isDevelopment && isBrowser;
/* ------------------------------------------------------------------------------------------------
Helper
------------------------------------------------------------------------------------------------ */
const hasOptionFn = options => name => _.get(options, name, false);
/* ------------------------------------------------------------------------------------------------
Component
------------------------------------------------------------------------------------------------ */
export function createHocWithMobx(Ctx, config) {
let counter = 0;
let testProps = {};
const logHooks = _.get(config, 'logHooks', false);
const logRender = _.get(config, 'logRender', false);
return (WrappedComponent, options) => {
const componentName = WrappedComponent.name || WrappedComponent.displayName;
const isReactComponent = WrappedComponent.prototype.hasOwnProperty('render');
const hasOption = hasOptionFn(options);
if (hasOption('noExtraProps')) {
return observer(props => {
// Avoid Proptypes to warn about using observables instead of js primitives
const flatProps = _.mapValues(props, value => toJS(value));
return <WrappedComponent { ...flatProps }/>;
});
}
/* --------------------------------------------------------------------------------------------- */
if (isTest) {
const TestingComponent = props => {
const getTestProps = _.get(props, 'testProps', false);
if (getTestProps) testProps = getTestProps;
const extendedProps = hasOption('noExtraProps')
? { ...testProps, ...props }
: { ...testProps, inner: props };
return (
<WrappedComponent { ...extendedProps }/>
);
};
TestingComponent.displayName = componentName;
return TestingComponent;
}
/* --------------------------------------------------------------------------------------------- */
return observer(class MyCompClass extends React.Component {
constructor(props, context) {
super(props, context);
this.hook = (name, nextProps) => {
const method = hasOption(name);
const useProps = nextProps
? { ...this.extendedProps, inner: nextProps }
: this.extendedProps;
if (method) method(useProps);
if (shouldLog && logHooks) {
console.log(name, ' -->', componentName, useProps);
}
};
}
static displayName = componentName;
@computed get extendedProps() {
return {
inner: this.props,
data: Ctx.data,
state: Ctx.state,
actions: Ctx.actions,
utils: Ctx.utils,
};
}
componentWillMount() {
this.hook('willMount');
}
componentWillUnmount() {
this.hook('willUnmount');
}
componentWillUpdate(nextProps) {
this.hook('willUpdate', nextProps);
}
componentDidUpdate() {
this.hook('didUpdate');
}
componentDidMount() {
this.hook('didMount');
}
render() {
if (shouldLog && logRender) {
counter++;
console.log('render', counter, componentName);
}
if (isReactComponent) return <WrappedComponent { ...this.extendedProps }/>;
return WrappedComponent.call(this, this.extendedProps, this.context);
}
});
};
}
import { createHocWithMobx } from '/imports/common/utils/hoc';
import Context from '/module/api/context';
export default createHocWithMobx(Context, {
logRender: false,
logHooks: false,
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment