-
-
Save Voles/a3d059c41ace356e8b3814e551ad1df5 to your computer and use it in GitHub Desktop.
React, removeEventListener and bind(this) gotcha
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
/* Sometimes it's pretty easy to run ito troubles with React ES6 components. | |
Consider the following code: */ | |
class EventStub extends Component { | |
componentDidMount() { | |
window.addEventListener('resize', this.onResize.bind(this)); //notice .bind | |
} | |
componentWillUnmount() { | |
window.removeEventListener('resize', this.onResize.bind(this)); | |
} | |
onResize() { | |
this.setState({width: this.div.offsetWidth}); | |
} | |
render() { return null; } | |
} | |
/* As a result EventListener won't be removed since A new function reference is created after .bind() is called. | |
(more http://stackoverflow.com/questions/11565471/removing-event-listener-which-was-added-with-bind | |
and http://alexfedoseev.com/post/65/react-event-handlers-and-context-binding). | |
Obviously this is not React's fault, it's how DOM works, but it's super easy to make a mistake. ESLint rule anyone? | |
What about solutions? Pretty straightforward one is to create bound funciton only once in constructor, | |
assign to internal prop and then use it:*/ | |
this.bound_onResize = this.onResize(bind); | |
//or replace the funtion with the bound one that allows to use same function: | |
this.onResize = this.onResize.bind(this); | |
//another options is to use arrow funciton on a class level so it'll capture "this" automatically, | |
//but this is as of Jan 2016 Stage 2 ES2016 (ES7) proposal and requires "babel experimental" flag | |
export class MyComponent extends Component { | |
onResize = () => this.onResize() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment