Reputation: 431
I am trying to open a popup only after the user mouses over an icon for one second to prevent triggering it by accident.
The only way I found to do this was using setTimeout on a handler function the problem is that for this to work I have to declare a global variable to the React component. This works but I'd rather not use a global variable this way.
let timer;
export default class Users extends Component {
state = {
popoverOpen: false,
};
handleMouseOver = (e) => {
e.stopPropagation();
switch (e.type) {
case 'mouseover':
clearTimeout(timer);
timer =
setTimeout(() => {
this.setState({
popoverOpen: true
});
}, 1000);
break;
case 'mouseout':
clearTimeout(timer);
break;
default:
console.log(e.type);
break;
}
};
Is there a way to set and clear the timeout using the local state or if not is there a better way to do this that is escaping me?
Thank you.
Upvotes: 3
Views: 633
Reputation: 23545
Using the upper class to store the timer and state data it look like :
class A {
constructor() {
this.state = false;
}
func() {
if (this.state) {
console.log('push the call');
clearTimeout(this.timer);
} else {
console.log('initial call');
}
this.state = true;
this.timer = setTimeout(() => {
this.state = false;
console.log('Call ended');
}, 500);
};
};
const a = new A();
a.func();
for (let i = 0; i < 5; i += 1) {
setTimeout(() => a.func(), i * 200);
}
Or if you do not want to pollute your class, wrap the function inside of an IIFE where you can store data
I've created a snippet example and then an usable react example to put on your code (because handleMouseOver = (e) => {
do not work in plain js)
class A {};
const a = new A();
a.func = (() => {
let state = false;
let timer;
return () => {
if (state) {
console.log('push the call');
clearTimeout(timer);
} else {
console.log('initial call');
}
state = true;
timer = setTimeout(() => {
state = false;
console.log('Call ended');
}, 500);
};
})();
for (let i = 0; i < 5; i += 1) {
setTimeout(() => a.func(), i * 200);
}
class A {
func = (() => {
let state = false;
let timer;
return () => {
if (state) {
console.log('push the call');
clearTimeout(timer);
} else {
console.log('initial call');
}
state = true;
timer = setTimeout(() => {
state = false;
console.log('Call ended');
}, 500);
};
})();
};
Upvotes: 2