Skip to content

Instantly share code, notes, and snippets.

@beaucharman
Last active May 25, 2016 06:37
Show Gist options
  • Save beaucharman/6805982a365ff7036c6cbd912b52e6bd to your computer and use it in GitHub Desktop.
Save beaucharman/6805982a365ff7036c6cbd912b52e6bd to your computer and use it in GitHub Desktop.
Experimenting with React Higher Order Components as Mixins
// 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