Last active
May 25, 2016 06:37
-
-
Save beaucharman/6805982a365ff7036c6cbd912b52e6bd to your computer and use it in GitHub Desktop.
Experimenting with React Higher Order Components as Mixins
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://gist.github.com/sebmarkbage/ef0bf1f338a7182b6775#gistcomment-1770639 | |
// "If your higher order component need state or lifecycle methods use this:"" | |
const hoc = C => class _hoc extends React.Component { | |
render() { | |
return <C {...this.props}/>; | |
} | |
} | |
// "If you don´t need state or lifecycle methods on your HOC this snip is more functional:"" | |
const hoc = C => _hoc(props) => { | |
return <C { ...props }/>; | |
} | |
// experimenting... | |
// const React | |
// const ReactDOM | |
const { Component, PropTypes } = React | |
const { render } = ReactDOM | |
class Foo extends Component { | |
render() { | |
const { children, context, data, update } = this.props | |
return ( | |
<p>Foo + [{children}] + {context} + {update && <button onClick={update}>Conter: {data.count}</button>}</p> | |
) | |
} | |
} | |
Foo.propTypes = { | |
children: PropTypes.node, | |
context: PropTypes.string, | |
data: PropTypes.object, | |
} | |
Foo.defaultProps = { | |
context: 'foo-default-context', | |
} | |
class Bar extends Component { | |
render() { | |
const { children, context, data } = this.props | |
return ( | |
<p>Bar + [{children}] + {context} + {data.language}</p> | |
) | |
} | |
} | |
Bar.propTypes = { | |
children: PropTypes.node, | |
context: PropTypes.string, | |
data: PropTypes.object, | |
} | |
Bar.defaultProps = { | |
context: 'bar-default-context', | |
data: { language: 'English' }, | |
} | |
const One = (props) => <div>{props.children}</div> | |
const Two = (props) => <div>{props.children}</div> | |
const Three = (props) => <div>{props.children}</div> | |
class Nested extends Component { | |
render() { | |
const { children, context } = this.props | |
return ( | |
<p>Nested + [{children}] + {context}</p> | |
) | |
} | |
} | |
const mixin = (InnerComponent, id = 1) => class extends Component { | |
constructor(props) { | |
super(props) | |
this.update = this.update.bind(this) | |
this.state = { | |
language: '日本語', | |
count: 1, | |
} | |
} | |
update() { | |
this.setState({ | |
count: this.state.count + 1, | |
}) | |
} | |
componentDidMount() { | |
console.log(`I am currently wrapping ${InnerComponent.name}`) | |
} | |
render() { | |
const children = this.props.children | |
return ( | |
<InnerComponent | |
context={`higher-order-context-${id}`} | |
data={this.state} | |
update={this.update} | |
{...this.props} | |
> | |
{children} | |
{children && ' + '}<strong>This is a child from the mixin</strong> | |
</InnerComponent> | |
) | |
} | |
} | |
const NewFoo = mixin(Foo) | |
const NewBar = mixin(Bar, 10) | |
const NewNested = mixin(Nested, 67) | |
const App = () => ( | |
<main> | |
<Foo>Foo-children</Foo> | |
<NewFoo>NewFoo-children</NewFoo> | |
<Bar>Bar-children</Bar> | |
<NewBar>NewBar-children</NewBar> | |
<One> | |
<Two> | |
<Three> | |
<NewNested /> | |
</Three> | |
</Two> | |
</One> | |
</main> | |
) | |
render(<App />, document.getElementById('main')) | |
/** | |
* yields > | |
<main> | |
<p>Foo + [Foo-children] + foo-default-context</p> | |
<p>Foo + [NewFoo-children + <strong>This is a child from the mixin</strong>] + higher-order-context-1 + <button data-reactid=".0.1.5"><span>Conter: </span><span>1</span></button></p> | |
<p>Bar + [Bar-children] + bar-default-context + English</p> | |
<p>Bar + [NewBar-children + <strong>This is a child from the mixin</strong>] + higher-order-context-10 + 日本語</p> | |
<p>Nested + [<strong>This is a child from the mixin</strong>] + higher-order-context-67</p> | |
</main> | |
// console > | |
// > "I am currently wrapping Foo" | |
// > "I am currently wrapping Bar" | |
// > "I am currently wrapping Nested" | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment