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>
  );
}