Created
November 25, 2017 12:40
-
-
Save jaredwilli/eaab6f1a2ef1cc3650c408d78a5b69cb to your computer and use it in GitHub Desktop.
HOC boiled eggs
This file contains hidden or 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 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} /> | |
| } | |
| } | |
| } | |
This file contains hidden or 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 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() | |
| }) |
This file contains hidden or 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
| // 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) | |
| } | |
| }) | |
| ) |
This file contains hidden or 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 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