Skip to content

Instantly share code, notes, and snippets.

@jaredwilli
Created November 25, 2017 12:40
Show Gist options
  • Select an option

  • Save jaredwilli/eaab6f1a2ef1cc3650c408d78a5b69cb to your computer and use it in GitHub Desktop.

Select an option

Save jaredwilli/eaab6f1a2ef1cc3650c408d78a5b69cb to your computer and use it in GitHub Desktop.
HOC boiled eggs
import React, { Component, PropTypes } from 'react'
import window from 'global/window'
import wrapDisplayName from 'recompose/wrapDisplayName'
import { createChangeEmitter } from 'change-emitter'
export const reactHOC = BaseComponent => {
return class ReactHOC extends Component {
static displayName = wrapDisplayName(BaseComponent, 'ReactHOC')
static propTypes = {
b: PropTypes.bool,
c: PropTypes.bool
}
static defaultProps = {
b: false,
c: false
}
constructor(props) {
super(props)
this.state = {}
this.channel = createChangeEmitter()
}
componentWillMount() {
this.subscribe(this.updateContext)
}
componentDidMount() {
this.on(['keydown'], this.updateState)
this.updateState()
}
componentWillUnmount() {
this.off(['keydown'], this.updateState)
this.b.unsubscribe(this.updateState)
}
componentWillReceiveProps() {
this.updateState()
}
updateContext() {
console.log('context updated', this.context)
}
updateState() {
console.log('state updated', this.state)
}
subscribe(...args) {
return this.channel.listen(...args)
}
unsubscribe() {
return this.channel() // implicit unsubscribe
}
on(events, callback) {
return events.forEach(evt => window.addEventListener(evt, callback))
}
off(events, callback) {
return events.forEach(evt => window.removeEventListener(evt, callback))
}
render() {
return <BaseComponent {...this.props} />
}
}
}
import global from 'global'
import document from 'global/document'
import window from 'global/window'
import React from 'react'
import tap from 'tap'
import { typeov } from 'typeov'
import { shallow } from 'enzyme'
import { reactHOC } from '.'
global.window = window
global.document = document
const test = tap.test
const StubComponent = () => <div>Hello World</div>
const ComposedComponent = reactHOC(StubComponent)
test('wraps `displayName`', t => {
const fixture = shallow(<ComposedComponent />)
t.equal(ComposedComponent.displayName, 'ReactHOC(StubComponent)', 'when wrapped')
t.equal(fixture.name(), 'StubComponent', 'when natural')
t.end()
})
test('provides a `b` prop', t => {
const fixture = shallow(<ComposedComponent />)
t.includes(fixture.props(), { b: false }, 'includes hoc props')
t.equal(typeov(fixture.props().b), 'boolean', 'is an array')
t.end()
})
test('returns the original component', t => {
const fixture = shallow(<ComposedComponent />)
t.equal(fixture.text(), '<StubComponent />', 'includes original component')
t.end()
})
test('properly cascades props', t => {
const fixture = shallow(<ComposedComponent a={true} b={true} />)
t.includes(fixture.props(), { a: true, b: true }, 'extends original')
t.end()
})
// https://github.com/acdlite/recompose/blob/master/docs/API.md
import React, { PropTypes as T } from 'react'
import compose from 'recompose/compose'
import withState from 'recompose/withState'
import withHandlers from 'recompose/withHandlers'
import setPropTypes from 'recompose/setPropTypes'
import mapProps from 'recompose/mapProps'
import wrapDisplayName from 'recompose/wrapDisplayName'
export const reactHOC = compose(
mapProps(({ ...rest }) => ({
...rest,
c: true,
d: true
})),
setPropTypes({
c: T.bool,
d: T.bool
}),
withState('value', 'updateValue', ''),
withHandlers({
onChange: props => event => {
props.updateValue(event.target.value)
}
})
)
import global from 'global'
import document from 'global/document'
import window from 'global/window'
import React from 'react'
import tap from 'tap'
import withProps from 'recompose/withProps'
import { typeov } from 'typeov'
import { mount, shallow, render } from 'enzyme'
import { reactHOC } from './index.recompose'
global.window = window
global.document = document
const test = tap.test
const StubComponent = withProps({ a: true, b: true })('div')
const ComposedComponent = reactHOC(StubComponent)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment