英文:
OnMouseLeave Event only firing after the mouse pointer leaves parent element
问题
我有一个包含OnMouseEnter()
的div元素,它会更改其类,并且有一个OnMouseLeave()
,会恢复其类,onMouseLeave()
只在鼠标指针离开元素的父div后起作用。
更多细节 - 基本上,我有一个父div(称为canvas),其中包含子div(cells)来表示矩阵,子div在鼠标进入时改变颜色,并在鼠标离开时恢复到原始颜色,问题是cells在鼠标进入时改变颜色,但只有在指针离开它们的父div时才恢复颜色。
const [canvas, setcanvas] = useState([[]]);
const handleenter1 = (row, col) => {
const a = []
for (var i = 0; i<50; i++){
a.push([]);
for (var j=0; j<20; j++){
if (i=== row && j === col){
var obj = {x: i, y: j, status: "wall"};
a[i].push(obj);
}
else {
obj = canvas[i][j];
a[i].push(obj);
}
}
}
setcanvas(a);
}
const handleleave1 = (row, col ) => {}
const create = () => {
let a = [];
for (var i = 0; i<50; i++){
a.push([]);
for (var j=0; j<20; j++){
if (i === 10 && j === 10){
var obj = {x: i, y: j, status: "starter"};
a[i].push(obj);
}
else {
obj = {x: i, y: j, status: "space"};
a[i].push(obj);
}
}
}
setcanvas(a);
}
useEffect(create, []);
const m = canvas.map((objlist,index1)=> {
return (objlist.map((obj,index) => {
return (
<div key = {`${index1} ${index}`}
onMouseEnter ={()=> {handleenter1(obj.x,obj.y)}}
onMouseLeave = {()=> { handleleave1(obj.x ,obj.y) }}>
</div>);
}));
});
英文:
I have a div element with OnMouseEnter()
that changes its class and a OnMouseLeave()
that reverts its class, the onMouseLeave()
only works after the mouse pointer leaves the parent div of the element.
Working example here - https://codesandbox.io/s/old-violet-7ipbvb?file=/src/Grid.jsx&resolutionWidth=320&resolutionHeight=675
More details - Basically I have a parent div (called canvas) that has child divs (cells) inside to represent a matrix, the child divs change color on mouse enter and revert to original color on mouseleave, the problem is that cells change color on mouse enter but only revert the color when the pointer leave their parent div.
const [canvas, setcanvas] = useState([[]]);
const handleenter1 = (row, col) => {
const a = []
for (var i = 0; i<50; i++){
a.push([]);
for (var j=0; j<20; j++){
if (i=== row && j === col){
var obj = {x: i, y: j, status: "wall"};
a[i].push(obj);
}
else {
obj = canvas[i][j];
a[i].push(obj);
}
}
}
setcanvas(a);
}
const handleleave1 = (row, col ) => {}
const create = () => {
let a = [];
for (var i = 0; i<50; i++){
a.push([]);
for (var j=0; j<20; j++){
if (i === 10 && j === 10){
var obj = {x: i, y: j, status: "starter"};
a[i].push(obj);
}
else {
obj = {x: i, y: j, status: "space"};
a[i].push(obj);
}
}
}
setcanvas(a);
}
useEffect(create, []);
const m = canvas.map((objlist,index1)=> {
return (objlist.map((obj,index) => {
return (
<div key = {`${index1} ${index}`}
onMouseEnter ={()=> {handleenter1(obj.x,obj.y)}}
onMouseLeave = {()=> { handleleave1(obj.x ,obj.y) }}>
</div>);
}));
});
答案1
得分: 1
问题出在你的handleenter1
和handleleave1
函数之间存在竞态条件,其中mouseleave
在及时看不到更新的canvas
,这就是为什么它错误地保留了先前的黑色单元格。
如果你重构这些函数以命令式地更新已知行/列的画布状态,就不会遇到这个问题。现在setcanvas
不会发生冲突,因为它只是设置它关心的一个单元格,而不是所有其他单元格。
这里是一个可运行的沙盒:
const handleenter1 = (row, col) => {
setcanvas((c) => {
const p = [...c];
p[row][col].status = "wall";
return p;
});
};
const handleleave1 = (row, col) => {
setcanvas((c) => {
const p = [...c];
p[row][col].status = "space";
return p;
});
};
英文:
The issue is a race-condition between your handleentter1
and handleleave1
functions where mouseleave does not see the updated canvas
in time, which is why it mistakenly keeps the previous cell black.
If you refactor the functions to imperatively update the canvas state's status for the known row/column, you won't run into this issue. Now the setcanvas
does not collide since it's just setting the one cell it cares about and not all the other cells.
Here's a working sandbox:
const handleenter1 = (row, col) => {
setcanvas((c) => {
const p = [...c];
p[row][col].status = "wall";
return p;
});
};
const handleleave1 = (row, col) => {
setcanvas((c) => {
const p = [...c];
p[row][col].status = "space";
return p;
});
};
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论