Skip to content

Instantly share code, notes, and snippets.

@bencooling
Forked from jquense/0. intro.md
Last active February 8, 2016 00:16
Show Gist options
  • Save bencooling/0fa19c07e4198d21022c to your computer and use it in GitHub Desktop.
Save bencooling/0fa19c07e4198d21022c to your computer and use it in GitHub Desktop.
Alternative ways to define react Components

The 0.13.0 improvements to React Components are often framed as "es6 classes" but being able to use the new class syntax isn't really the big change. The main thing of note in 0.13 is that React Components are no longer special objects that need to be created using a specific method (createClass()). One of the benefits of this change is that you can use the es6 class syntax, but also tons of other patterns work as well!

Below are a few examples creating React components that all work as expected using a bunch of JS object creation patterns (https://github.com/getify/You-Dont-Know-JS/blob/master/this%20&%20object%20prototypes/ch4.md#mixins). All of the examples are of stateful components, and so need to delegate to React.Component for setState(), but if you have stateless components each patterns tends to get even simpler. The one major caveat with react components is that you need to assign props and context to the component instance otherwise the component will be static. The reason is that when reconciling updates to props, new instances aren't created props is jsut set to the next props.

Why might you use these patterns? Some are just nicely terse, or maybe you just like the library you are already using for object creation, but generally these patterns offer a lot more in terms of flexibility and functionality. For instance, since most examples are created in a closure you get private variables for free!

function PlainOldObjectComponent(props, context){
var instance = Object.create(React.Component.prototype)
instance.props = props
instance.context = context
instance.state = { message: 'Object literals ftw' }
instance.render = function() {
return <li>
<button onClick={ e => this.setState({ message: 'stateful!' })}>
{this.state.message}
</button>
</li>
}
return instance
}
function MixinComponent(props, context) {
return {
...React.Component.prototype,
props,
context,
state: {
message: 'Instances through Extension'
},
render() {
return <li>
<button onClick={ e => this.setState({ message: 'stateful!' })}>
{this.state.message}
</button>
</li>
}
}
}
function ParasiticComponent(props, context){
var instance = new React.Component(props, context)
instance.state = { message: 'Let me just add a method to this one..' }
instance.render = function() {
return <li>
<button href='#' onClick={()=> this.setState({ message: 'stateful!' })}>
{this.state.message}
</button>
</li>
}
return instance
}
// Stampit is an excellent library by Eric Elliott for object creation.
// https://github.com/ericelliott/stampit
var ReactStamp = stampit.convertConstructor(React.Component)
// ^^^ convenience method for:
// stampit().methods(React.Component.prototype).enclose(React.Component)
var StampitComponent = stampit()
.enclose(function () {
this.state = { message: 'I can even use stampit!' }
})
.methods({
render() {
return <li>
<button href='#' onClick={()=> this.setState({ message: 'stateful!' })}>
{this.state.message}
</button>
</li>
}
});
StampitComponent = stampit.compose(ReactStamp, StampitComponent);
f = { foo: function(){ return 'foo'; } };
b = { bah: function(){ return this.foo(); } };
b.bah() // TypeError: this.foo is not a function. (In 'this.foo()', 'this.foo' is undefined)
o = Object.assign(f,b);
o.bah(); // "foo"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment