如何在React(Codesandbox)应用中实现悬停按钮启动的定时器启停功能?
Got it, let's adjust your code so the timer only runs when you're hovering over the button. Here's how to make that happen:
First, we'll replace your existing useEffect with one that ties the timer's activation directly to the hover state (isShown). We'll use setInterval instead of repeated setTimeout calls for a more reliable recurring timer, and ensure we clean it up properly when you stop hovering or the component unmounts.
Here's the modified code:
import React, { useState, useEffect } from "react"; function App() { const [isShown, setIsShown] = useState(false); const [time, setTime] = useState({ seconds: 0, minutes: 0, hours: 0 }); useEffect(() => { let intervalId; // Start the timer when hovering begins if (isShown) { intervalId = setInterval(() => { // Use functional update to access the latest time state setTime(prevTime => { let { seconds, minutes, hours } = prevTime; seconds++; if (seconds > 59) { minutes++; seconds = 0; } if (minutes > 59) { hours++; minutes = 0; } if (hours > 24) { hours = 0; } return { seconds, minutes, hours }; }); }, 1000); } // Cleanup: Stop the timer when hovering ends or component unmounts return () => clearInterval(intervalId); }, [isShown]); // Re-run effect whenever hover state changes return ( <div className="App"> <button onMouseEnter={() => setIsShown(true)} onMouseLeave={() => setIsShown(false)} > Hover over me! </button> {isShown && ( <div> <p> {` ${time.hours < 10 ? "0" + time.hours : time.hours} : ${time.minutes < 10 ? "0" + time.minutes : time.minutes} : ${time.seconds < 10 ? "0" + time.seconds : time.seconds} `} </p> </div> )} </div> ); } export default App;
Key Changes Explained:
- Timer Tied to Hover State: The
useEffectnow triggers wheneverisShownchanges. WhenisShownistrue(you're hovering), we start an interval that updates the time every second. WhenisShownbecomesfalse, the cleanup function stops the timer. - Reliable Interval Timer: Using
setIntervalis more efficient than chainingsetTimeoutcalls here—it creates a consistent recurring timer that we can easily stop withclearInterval. - Functional State Update: We use
setTime(prevTime => ...)to ensure we're always working with the latest version of the time state, which avoids stale state bugs in the interval callback. - Cleanup Prevention: The cleanup function clears the interval whenever you stop hovering or the component unmounts, preventing memory leaks and unnecessary background timer runs.
- Unused State Removed: We deleted the
startTimerstate variable since it wasn't being used, simplifying the code.
Now your timer will only count time while you're hovering over the button, and pause immediately when you move your mouse away. The total time will persist between hovers (so if you hover for 5 seconds, leave, then come back, it picks up where it left off). If you wanted it to reset on each hover, just add setTime({ seconds: 0, minutes: 0, hours: 0 }) inside the onMouseEnter handler.
内容的提问来源于stack exchange,提问作者tallpotato

