Last active
March 3, 2019 23:55
-
-
Save townofdon/5d05175ab103dfd0e0e6347fd65e71e6 to your computer and use it in GitHub Desktop.
Autobind React Class Methods
This file contains 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 { Component } from 'react'; | |
/** | |
* Auto-bind all methods of a React class, excluding lifecycle methods | |
* | |
* USAGE: | |
* | |
* ``` | |
* class MyClass extends ComponentAutoBind { ... } | |
* ``` | |
*/ | |
class ComponentAutoBind extends Component { | |
constructor(props) { | |
super(props); | |
const prototype = Object.getPrototypeOf(this); | |
if (!prototype) { return this; } | |
if (typeof prototype !== 'object') { return this; } | |
const reservedFunctionNames = [ | |
'constructor', | |
'getDerivedStateFromProps', | |
'shouldComponentUpdate', | |
'render', | |
'componentDidMount', | |
'componentDidUpdate', | |
'componentWillUnmount', | |
'setState', | |
]; | |
const classPropertyNames = Object.getOwnPropertyNames(prototype); | |
classPropertyNames.forEach((propertyName) => { | |
if (reservedFunctionNames.includes(propertyName)) { | |
return; | |
} | |
if (!this[propertyName]) { | |
return; | |
} | |
if (typeof this[propertyName] !== 'function') { | |
return; | |
} | |
if (!prototype.hasOwnProperty(propertyName)) { | |
return; | |
} | |
this[propertyName] = this[propertyName].bind(this); | |
}); | |
return this; | |
} | |
} | |
module.exports = ComponentAutoBind; |
This file contains 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 from 'react'; | |
import ComponentAutoBind from './ComponentAutoBind'; | |
class MyClass extends ComponentAutoBind { | |
constructor (props){ | |
super(props); | |
this.state = { | |
a: 1, | |
b: 2, | |
c: 3, | |
}; | |
// note the conspicuous absence of bindings here... | |
} | |
// this event handler will now be bound! | |
// best of both worlds - hot-reloading still works, and | |
// event handler is always bound. | |
_handleActionNumeroUno() { | |
console.log('UNO'); | |
console.log(this.state); | |
} | |
// since this arrow function is transpiled as a constructor | |
// method, this method is not set on the class prototype. | |
// see: https://www.reactjunkie.com/demistifying-es6-class-method-and-property-initializer-arrow-function | |
// note - class properties as arrow functions can cause performance issues | |
// note - there is a history of hot-reloading not working for arrow functions. | |
_handleActionNumeroDos = () => { | |
console.log('DOS'); | |
console.log(this.state); | |
} | |
render() { | |
return ( | |
<div> | |
<button | |
className="btn-primary" | |
onClick={this._handleActionNumeroUno} | |
type="button" | |
> | |
uno!! | |
</button> | |
<button | |
className="btn-primary" | |
onClick={this._handleActionNumeroDos} | |
type="button" | |
> | |
dos!! | |
</button> | |
</div> | |
); | |
} | |
} | |
module.exports = ComponentAutoBind; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment