Last active
July 18, 2018 11:28
-
-
Save jmaguirrei/5f48a0087f1e391ef81d01ceed6a8c39 to your computer and use it in GitHub Desktop.
Example of a function that creates a hoc (Higher order component)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} | |
}); | |
}; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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