https://codepen.io/evan-jin/pen/qBjGWvR
const [hoverItem, setHoverItem] = useState(null)
const timerRef = useRef(null)
const addcursor = useCallback(() => {
console.log('addcursor')
clearTimeout(timerRef.current)
timerRef.current = null
timerRef.current = setTimeout(() => {
document.body.style.cursor = 'wait'
}, 10)
}, [])
const removeCursor = useCallback(() => {
if (timerRef.current === null) return
console.log('removeCursor')
timerRef.current = setTimeout(() => {
document.body.style.cursor = 'default'
}, 500)
}, [])
useEffect(() => {
if (hoverItem) {
addcursor()
} else {
removeCursor()
}
}, [hoverItem])
当鼠标悬停在div框上时,我想保持"等待光标",但当我停止移动光标时,setTimeout会触发。
我尝试在useEffect返回(willUnmount)上使用clearTimeout,但没有成功。
如果我在每个盒子组件上来回移动,它会起作用,但如果我快速将Cursor移动到另一个,它最终会触发RemoveCursor setTimeout。
综上所述,
- 我想在移出光标时保持"等待光标"500毫秒
- 经过框后,如果光标在框上,"等待光标"需要停留在框上而不是消失
这个问题看起来很奇怪,但我只是为我的真实项目做了这个简单的问题请任何人帮帮我。。!
我终于发现了问题!因为我在每个项目组件中声明了timerRef。因此,每个timerRef都引用了每个Item计时器。我可以通过在父组件中声明timerRef来简单地解决这个问题!我会把代码留在链接上。谢谢你们的努力。
看起来您不需要使用超时。你可以在没有setTimeout
的情况下实现你想要做的事情。
const { useState, useEffect, useCallback, useRef } = React
const Item = ({ num }) => {
const [hoverItem, setHoverItem] = useState(null)
const addCaption = useCallback(() => {
console.log('addCaption')
document.body.style.cursor = 'wait'
}, [])
const removeCaption = useCallback(() => {
console.log('removeCaption')
document.body.style.cursor = 'grab'
}, [])
useEffect(() => {
if (hoverItem) {
addCaption()
} else {
removeCaption()
}
}, [hoverItem])
return (
<div
className='square'
name={num}
id={num}
onMouseEnter={e => setHoverItem(e.target.id)}
onMouseLeave={e => setHoverItem(null)}
/>
)
}
const App = () => {
return (
<div className='wrapper'>
{[...Array(12)].map((_, i) => (
<Item key={i} num={i} />
))}
</div>
)
}
ReactDOM.render( <App/>, document.getElementById("root") )
因为您为每个Item提供了一个状态,但只需要一个状态(代表"光标是否在任何Item内")。只要将您的状态上移到父组件,您的代码就会工作。
const { useState, useEffect, useCallback, useRef } = React;
const Item = ({ num, onMouseEnter, onMouseLeave }) => {
return (
<div
className="square"
name={num}
id={num}
onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave}
/>
);
};
const App = () => {
const [hoverItem, setHoverItem] = useState(null);
const timerRef = useRef(null);
const addcursor = useCallback(() => {
console.log("addcursor");
document.body.style.cursor = "wait";
clearTimeout(timerRef.current);
}, []);
const removeCursor = useCallback(() => {
console.log("removecursor");
clearTimeout(timerRef.current);
timerRef.current = setTimeout(() => {
document.body.style.cursor = "default";
}, 500);
}, []);
useEffect(() => {
if (hoverItem) {
addcursor();
} else {
removeCursor();
}
}, [hoverItem]);
return (
<div className="wrapper">
{[...Array(12)].map((_, i) => (
<Item
key={i}
num={i}
onMouseEnter={(e) => setHoverItem(e.target.id)}
onMouseLeave={(e) => setHoverItem(null)}
/>
))}
</div>
);
};
ReactDOM.render(<App />, document.getElementById("root"));