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()
}
@hrc7505
Copy link

hrc7505 commented May 15, 2017

I have two components and in both the components I am adding a hashChange listener and removing same way you told. But when first component is unmounted its hashChange event is still called and vice-versa.
What's the problem? Is it a bug?

@Khachatour
Copy link

Great!! Thank you mate! Saved me!

@Belyash
Copy link

Belyash commented Jun 5, 2017

Thank you!

@cronnelo
Copy link

Thank you very much!

@zishan74750
Copy link

thanks for explaination

@tw15egan
Copy link

tw15egan commented Jun 21, 2017

Thanks for this! 👍 🎉

@sikor144
Copy link

Thanks for this! 👍

@cathyxz
Copy link

cathyxz commented Aug 18, 2017

@riccardopiola
Copy link

Thank you very much

@xkal36
Copy link

xkal36 commented Sep 12, 2017

Very useful, much appreciated.

@quentinxhu
Copy link

Thanks 👍

@kstratis
Copy link

I was also bitten by this one. Thanks.

@gemmadlou
Copy link

Oh my days! Restuta! You saved me! Immediately I'm forking of course.

@hrkd
Copy link

hrkd commented Sep 25, 2017

Thanks!

@virgial
Copy link

virgial commented Sep 28, 2017

Great!

@imjamescrain
Copy link

Thank you!

@dbyzero
Copy link

dbyzero commented Oct 18, 2017

Thanks :)

@Falieson
Copy link

Thanks!

@parkerziegler
Copy link

What a hero! Just echoing the love from the folks above!

@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