React组件实现退出暂停计时器、登录恢复计时及登录页显示剩余时间的问题求助
React组件实现退出暂停计时器、登录恢复计时及登录页显示剩余时间的问题求助
看起来你现在遇到了三个核心问题:点击Exit按钮时计时器停不下来、登录后没法从暂停的时间继续计时,还有登录页面没法正确显示剩余时间。我来帮你逐个解决这些问题:
问题根源梳理
- 计时器引用丢失:你在
LabPart里用普通变量interval保存定时器,组件每次渲染都会重置这个变量,导致handleExitClick里的clearInterval找不到正确的定时器引用。 - 状态未持久化:组件卸载后内部状态会丢失,退出时的剩余时间没保存,登录后自然没法恢复。
- 登录页传参逻辑混乱:原代码里的
newTimeRemaining和未定义的x变量导致剩余时间无法正确展示。
完整修复代码
1. 修改LabPart.jsx
import React, { useState, useEffect, useRef } from 'react'; import Login from './Login'; const LabPart = ({ initialTime, password }) => { const [pass, setPass] = useState(password); // 优先从本地存储读取剩余时间,无值则用传入的初始时间 const [timeRemaining, setTimeRemaining] = useState(() => { const savedTime = localStorage.getItem('remainingTime'); return savedTime ? parseInt(savedTime) : initialTime; }); // 用useRef持久化定时器引用,避免渲染重置 const intervalRef = useRef(null); useEffect(() => { // 仅当用户登录且时间有效时启动定时器 if (pass && timeRemaining >= 0) { intervalRef.current = setInterval(() => { setTimeRemaining(prevTime => { const newTime = prevTime - 1; // 每次更新时间都同步到本地存储 localStorage.setItem('remainingTime', newTime.toString()); return newTime; }); }, 1000); } // 组件卸载或依赖变化时清除定时器 return () => { if (intervalRef.current) { clearInterval(intervalRef.current); } }; }, [pass, timeRemaining]); const handleExitClick = () => { console.log("logout successful"); // 清除定时器并清空引用 if (intervalRef.current) { clearInterval(intervalRef.current); intervalRef.current = null; } // 清空密码触发登录页跳转 setPass(""); }; const hours = Math.floor(timeRemaining / 3600); const minutes = Math.floor((timeRemaining % 3600) / 60); const seconds = timeRemaining % 60; return ( <> {pass && timeRemaining >= 0 ? ( <div> <p>Time remaining: {hours}h {minutes}m {seconds}s</p> <button onClick={handleExitClick}>Exit</button> </div> ) : ( <Login /> )} </> ) } export default LabPart;
2. 修改Login.jsx
import React, { useState } from "react"; import LabPart from "./LabPart"; import '../style/login.css'; const Login = () => { const [password, setPassword] = useState(""); const [openPage, setOpenPage] = useState(false); // 从本地存储读取剩余时间,无值则用默认10秒 const remainingTime = parseInt(localStorage.getItem('remainingTime')) || 10; const handlePasswordChange = (event) => { setPassword(event.target.value); }; const handleFormSubmit = (event) => { event.preventDefault(); if (password === "12345") { console.log("login successful"); setOpenPage(true); } else { alert("Incorrect Password") } }; const hours = Math.floor(remainingTime / 3600); const minutes = Math.floor((remainingTime % 3600) / 60); const seconds = remainingTime % 60; return ( <> {openPage ? ( <LabPart initialTime={remainingTime} password={password} /> ) : ( <form onSubmit={handleFormSubmit}> <input type="password" value={password} onChange={handlePasswordChange} placeholder="Enter password" /> <button type="submit">Enter</button> {/* 展示剩余时间 */} <p>Remaining Time: {hours}h {minutes}m {seconds}s</p> </form> )} </> ); }; export default Login;
关键修改说明
- useRef保存定时器:解决了
clearInterval无效的问题,useRef的.current属性在组件生命周期内保持引用不变。 - localStorage持久化时间:退出时的剩余时间会存在本地,登录后直接读取,确保状态不会丢失。
- 简化传参逻辑:去掉冗余的props,直接从本地存储读取数据,逻辑更清晰。
- 优化定时器启动条件:只有用户登录且时间有效时才启动定时器,避免无效运行。
这样修改后,点击Exit按钮时定时器会被正确清除,登录页面能显示剩余时间,登录后也会从暂停的时间继续计时啦。
备注:内容来源于stack exchange,提问作者torq1284
相关产品推荐
相关产品推荐

