Часть, которую вы действительно пропустили, является аннулированием обратного вызова тайм-аута, если сработало событие mouseLeave
. Для этого вам нужно удерживать возвращенное значение setTimeout
, чтобы вызвать clearTimeout
до истечения таймера ( или если компонент размонтируется !! )
Ниже приведено базовые c машины в компоненте на основе классов:
state = {
hovered: false
};
timer;
mouseEnterHandler = () => this.setState({ hovered: true });
mouseLeaveHandler = () => this.setState({ hovered: false });
onTimeout = () => {
// Do action
};
clearTimer = () => {
clearTimeout(this.timer);
};
// Here's the meat:
// If state updates, then componentDidUpdate is called,
// if the new hovered state is true, set timeout and save the
// returned reference, else clear the timeout using the saved
// timer reference.
componentDidUpdate() {
const { hovered } = this.state;
if (hovered) {
this.timer = setTimeout(this.onTimeout, 500);
} else {
this.clearTimer();
}
}
// This is component cleanup, if the component unmounts before
// the timer expires you may not want the "Do action" to fire,
// so we go ahead and clear the timeout so you're not accidentally
// accessing state/props of an unmounted component.
componentWillUnmount() {
this.clearTimer();
}
Ниже приводится эквивалентный функциональный компонент logi c:
const [hovered, sethovered] = useState(false);
const mouseEnterHandler = () => sethovered(true);
const mouseLeaveHandler = () => sethovered(false);
const onTimeout = () => {
// Do action
};
useEffect(() => {
const timer = hovered && setTimeout(onTimeout, 500);
return () => {
clearTimeout(timer);
};
}, [hovered]);