onMouseEnter/onMouseLeave 的处理间隔
Handling Interval with onMouseEnter/onMouseLeave
基本上我是在为网络应用程序制作一个通知系统。
系统使用包装整个应用程序的 NotificationProvider 组件:
function App() {
return (
<>
<Router>
<Navbar />
<NotificationProvider>
<Routes>
<Route path='/' element={<Home /> } />
<Route path='/terms' element={<Home /> } />
<Route path='/legal' element={<Home /> } />
<Route path='/sign-up' element={<SignUp /> } />
<Route path='/faq' element={<Questions />} />
<Route path='/about' element={<About />} />
<Route path='/privacy' element={<Privacy />} />
<Route path='/login' element={<Login />} />
</Routes>
<Footer />
</NotificationProvider>
</Router>
</>
);
}
NotificationProvider 组件只是处理信息并将其映射到另一个组件:
const NotificationProvider = (props) => {
const notifications = [{
id: v4(),
type: 'SUCCESS',
message: 'test'
}];
return (
<div>
<div className={'notification-wrapper'}>
{notifications.map(note => {
return <Notification key={note.id} {...note} />
})}
</div>
{props.children}
</div>
)
}
通知组件只显示道具并处理通知更改宽度的“进度条”。当鼠标位于通知顶部时,我试图暂停此时间栏。
const Notifications = (props) => {
const [width, setWidth] = useState(0);
const [intervalID, setIntervalID] = useState(null);
const handleStartTimer = () => {
console.log('start')
const id = setInterval(() => {
setWidth(prev => {
if (prev < 100) {
return prev + 0.5;
}
clearInterval(id);
return prev;
});
}, 20);
setIntervalID(id);
};
const pauseTimer = () => {
console.log('pause')
clearInterval(intervalID);
}
useEffect(() => {
handleStartTimer();
}, [])
return (
<div onMouseEnter={pauseTimer} onMouseLeave={handleStartTimer} className={`notification-item ${props.type === 'SUCCESS' ? 'success' : 'error'}`}>
<p>{props.message}</p>
<div className={'bar'} style={{width: `${width}%`}} />
</div>
)
}
我可以在控制台看到当我用鼠标进入或离开通知时正在调用该功能。但是,进度条从不暂停,所以我猜我在看不到哪里的间隔上做错了。
This is how the progress bar looks like
我猜这是因为您在 useEffect 中定义了 clearInterval。
您无法从 useEffect 外部访问包含 clearIntervall 的 id 变量。如果你想访问 interval,你必须首先在 useEffect 范围之外定义它,这样才能访问它,像这样的一些技巧。
这就是为什么当您调用 pauseTimer 函数时,它不会清除间隔
您可以改为这样做:将 setInterval 存储在 ref 中,并将 setIntervall 的调用和控件放在 useEffect 中,这样您就可以完全控制它。
import React, {useEffect, useRef, useState } from 'react'
export default function App() {
const intvl = useRef(null);
const [count, setCount] = useState(0);
const [pause, setPause] = useState(false)
const inc = () => setCount(prev => prev + 0.5)
const handleStartTimer = () => setPause(false)
const handlePauseTimer = () => setPause(true)
useEffect(()=> {
!pause ?
intvl.current = setInterval(inc, 20)
:
clearInterval(intvl.current)
count === 100 && clearInterval(intvl.current)
return () => clearInterval(intvl.current)
},[pause, count])
return (
<div>
<h1>{count}</h1>
<div
onMouseEnter={handleStartTimer}
onMouseLeave={handlePauseTimer}
>
pause/start
</div>
</div>
);
}
基本上我是在为网络应用程序制作一个通知系统。
系统使用包装整个应用程序的 NotificationProvider 组件:
function App() {
return (
<>
<Router>
<Navbar />
<NotificationProvider>
<Routes>
<Route path='/' element={<Home /> } />
<Route path='/terms' element={<Home /> } />
<Route path='/legal' element={<Home /> } />
<Route path='/sign-up' element={<SignUp /> } />
<Route path='/faq' element={<Questions />} />
<Route path='/about' element={<About />} />
<Route path='/privacy' element={<Privacy />} />
<Route path='/login' element={<Login />} />
</Routes>
<Footer />
</NotificationProvider>
</Router>
</>
);
}
NotificationProvider 组件只是处理信息并将其映射到另一个组件:
const NotificationProvider = (props) => {
const notifications = [{
id: v4(),
type: 'SUCCESS',
message: 'test'
}];
return (
<div>
<div className={'notification-wrapper'}>
{notifications.map(note => {
return <Notification key={note.id} {...note} />
})}
</div>
{props.children}
</div>
)
}
通知组件只显示道具并处理通知更改宽度的“进度条”。当鼠标位于通知顶部时,我试图暂停此时间栏。
const Notifications = (props) => {
const [width, setWidth] = useState(0);
const [intervalID, setIntervalID] = useState(null);
const handleStartTimer = () => {
console.log('start')
const id = setInterval(() => {
setWidth(prev => {
if (prev < 100) {
return prev + 0.5;
}
clearInterval(id);
return prev;
});
}, 20);
setIntervalID(id);
};
const pauseTimer = () => {
console.log('pause')
clearInterval(intervalID);
}
useEffect(() => {
handleStartTimer();
}, [])
return (
<div onMouseEnter={pauseTimer} onMouseLeave={handleStartTimer} className={`notification-item ${props.type === 'SUCCESS' ? 'success' : 'error'}`}>
<p>{props.message}</p>
<div className={'bar'} style={{width: `${width}%`}} />
</div>
)
}
我可以在控制台看到当我用鼠标进入或离开通知时正在调用该功能。但是,进度条从不暂停,所以我猜我在看不到哪里的间隔上做错了。
This is how the progress bar looks like
我猜这是因为您在 useEffect 中定义了 clearInterval。 您无法从 useEffect 外部访问包含 clearIntervall 的 id 变量。如果你想访问 interval,你必须首先在 useEffect 范围之外定义它,这样才能访问它,像这样的一些技巧。
这就是为什么当您调用 pauseTimer 函数时,它不会清除间隔
您可以改为这样做:将 setInterval 存储在 ref 中,并将 setIntervall 的调用和控件放在 useEffect 中,这样您就可以完全控制它。
import React, {useEffect, useRef, useState } from 'react'
export default function App() {
const intvl = useRef(null);
const [count, setCount] = useState(0);
const [pause, setPause] = useState(false)
const inc = () => setCount(prev => prev + 0.5)
const handleStartTimer = () => setPause(false)
const handlePauseTimer = () => setPause(true)
useEffect(()=> {
!pause ?
intvl.current = setInterval(inc, 20)
:
clearInterval(intvl.current)
count === 100 && clearInterval(intvl.current)
return () => clearInterval(intvl.current)
},[pause, count])
return (
<div>
<h1>{count}</h1>
<div
onMouseEnter={handleStartTimer}
onMouseLeave={handlePauseTimer}
>
pause/start
</div>
</div>
);
}