Reputation: 310
I have some react component and needed to work with "Enter" function.
class MyComponent extends Component {
componentDidMount() {
console.log('componentDidMount');
document.removeEventListener('keypress', this.enter);
document.addEventListener('keypress', this.enter.bind(this));
}
componentWillUnmount() {
console.log('componentWillUnmount');
document.removeEventListener('keypress', this.enter);
}
render() {
return (...);
}
enter(target) {
if (target.charCode === 13) {
console.log('fired');
/* after that component unmounted */
}
}
}
Console log show:
componentDidMount
fired
componentWillUnmount
, but when press Enter the console show again fired
.
Upvotes: 2
Views: 1444
Reputation: 1075925
this.enter.bind(this)
returns a new function, which is not the same function as this.enter
. So your removeEventListener
is ignored, because that specific function isn't on the event list.
Remember the result of this.enter.bind(this)
and use that when removing.
componentDidMount() {
console.log('componentDidMount');
this.boundEnter = this.enter.bind(this);
document.addEventListener('keypress', this.boundEnter);
}
componentWillUnmount() {
console.log('componentWillUnmount');
document.removeEventListener('keypress', this.boundEnter);
}
(There's also no need for your removeEventListener
in componentDidMount
.)
Since you're using ES2015+ syntax, I'll assume you're transpiling. If you are, you could use an arrow function rather than a method for enter
:
class MyComponent extends Component {
componentDidMount() {
console.log('componentDidMount');
document.addEventListener('keypress', this.enter);
}
componentWillUnmount() {
console.log('componentWillUnmount');
document.removeEventListener('keypress', this.enter);
}
render() {
return (...);
}
enter = target => {
if (target.charCode === 13) {
console.log('fired');
/* after that component unmounted */
}
};
}
That requires that you enable handling of class properties in your transpiler (in Babel, they're currently part of the stage-2
preset).
Upvotes: 2
Reputation: 193301
You never unbind event handler. The problem is that this.enter.bind(this)
and this.enter
are different functions because Function.prototype.bind creates new "wrapper" function from the original.
Try something like this:
class MyComponent extends Component {
constructor () {
this.enter = this.enter.bind(this)
}
componentDidMount() {
console.log('componentDidMount');
document.removeEventListener('keypress', this.enter);
document.addEventListener('keypress', this.enter);
}
componentWillUnmount() {
console.log('componentWillUnmount');
document.removeEventListener('keypress', this.enter);
}
render() {
return (...);
}
enter(target) {
if (target.charCode === 13) {
console.log('fired');
/* after that component unmounted */
}
}
}
Note, you need to provide the same function to both addEventListener
and removeEventListener
.
Upvotes: 2