Skip to content

Instantly share code, notes, and snippets.

@Restuta
Last active March 16, 2024 00:22
Show Gist options
  • Save Restuta/e400a555ba24daa396cc to your computer and use it in GitHub Desktop.
Save Restuta/e400a555ba24daa396cc to your computer and use it in GitHub Desktop.
React, removeEventListener and bind(this) gotcha
/* 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 funtion:
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()
}
@rijulg
Copy link

rijulg commented Nov 27, 2017

This saved me a tonne of time, thanks :D

@rIpteyed
Copy link

rIpteyed commented Dec 5, 2017

Excellent tips. Thank you!!

@Leif-Frederiksen
Copy link

Super - saved my day :-)

@italoborges
Copy link

Thanks man! I was struggling with this for awhile! Cheers!

@pincheira
Copy link

pincheira commented May 3, 2018

Amazing! Thank you.

Removing the listener works wonders, so I don't have to call .bind(this) to avoid -as you said- creating a new function reference. I ended up doing this on my component:

export default class MyComponent extends React.Component {

  componentDidMount() {
    document.addEventListener('keyup', this.onKeyUp);
  }

  componentWillUnmount() {
    document.removeEventListener('keyup', this.onKeyUp);
  }

  onKeyUp = (e) => {
    if (e.keyCode === 27) { // ESC key
      this.dismissDialog();
    }
  }

}

@supersime
Copy link

Helped me too... had to post. Thanks.

@Nachasic
Copy link

Thank you!

@ryanQL
Copy link

ryanQL commented Sep 13, 2018

Brilliant. Thank you!

@manifoldhiker
Copy link

Thank you, helped me!

@dshabin
Copy link

dshabin commented Oct 6, 2018

Thank you, helped me!!!!!!

@DmitriyWebDev
Copy link

Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment