Проблема
Я думаю, что основная проблема с вашей реализацией заключается в том, как асинхронные обратные вызовы событий ставятся в очередь и обрабатываются в событии l oop. Я не могу найти каких-либо подробных сведений о задержке обработки обратных вызовов событий, но документы здесь и здесь могут пролить немного света на этот вопрос, если вы хотите углубиться.
В основном проблема двоякая:
- Одно событие l oop требует минутной продолжительности для обработки, т. Е. Обнаружения события и добавления его в очередь. Я подозреваю, что мышь движется достаточно быстро с экрана или с экрана или в другой div, который не обнаруживается. Дивы "прыжок" / "перемещение" при наведении также не очень помогают.
- Компонент logi c предполагает, что все события могут и будут обнаружены, и просто переключает предыдущее существующее состояние. Как только событие пропущено, переключение инвертируется, поэтому вы видите проблему. Даже в обновленной песочнице эта задержка может привести к зависанию одного из элементов.
Предлагаемое решение
Добавьте прослушиватель событий перемещения мыши к объекту окна и проверьте, Цель события перемещения мыши содержится в одном из ваших элементов. Если в данный момент не зависает и элемент содержит цель события, установите isHovered
true, а если в настоящее время завис и элемент не содержит цель события, установите isHovered
false.
This isn ' t полная замена прослушивателей событий enter / leave | over / out, прикрепленных к содержащему div
, поскольку я все еще мог воспроизвести крайний случай. Я заметил, что ваш пользовательский интерфейс наиболее подвержен этой проблеме при быстром перемещении мыши и выходе из окна. намного сложнее). Что также, похоже, немного помогло, так это отсутствие определения анонимных функций обратного вызова для div.
import React, { createRef } from "react";
export default class Geo extends React.Component {
state = {
isHovering: false
};
mouseMoveRef = createRef();
componentDidMount() {
window.addEventListener("mousemove", this.checkHover, true);
}
componentWillUnmount() {
window.removeEventListener("mousemove", this.checkHover, true);
}
setHover = () => this.setState({ isHovering: true });
setUnhover = () => this.setState({ isHovering: false });
checkHover = e => {
if (this.mouseMoveRef.current) {
const { isHovering } = this.state;
const mouseOver = this.mouseMoveRef.current.contains(e.target);
if (!isHovering && mouseOver) {
this.setHover();
}
if (isHovering && !mouseOver) {
this.setUnhover();
}
}
};
render() {
var textDisplay;
if (this.state.isHovering) {
textDisplay = <span>HOVERING</span>;
} else {
textDisplay = <h1>NOT HOVERING</h1>;
}
return (
<div
ref={this.mouseMoveRef}
onMouseEnter={this.setHover}
onMouseLeave={this.setUnhover}
style={{ width: 300, height: 100, background: "green" }}
>
{textDisplay}
</div>
);
}
}
Редактировать friendly-chatterjee-xx2ms