javascript - 不确定如何在更改导航选项卡时停止计时器重置
问题描述
Codesandbox我有一个应用程序,它记录用户在应用程序内页面上的屏幕时间。但是,当我在导航栏选项卡(“关于”和“时间”)之间单击时,计时器会重置。
我不希望它重置。我希望它在我更改导航栏选项卡后暂停,并在我返回同一选项卡时恢复。我尝试使用 setInterval 而不是 setTimeout 但没有任何变化。
关于.js
import React, { useState, useEffect } from 'react';
const About = () => {
const [time, setTime] = useState({
seconds: 0,
minutes: 0,
hours: 0,
});
useEffect(() => {
let isCancelled = false;
const advanceTime = () => {
setInterval(() => {
let nSeconds = time.seconds;
let nMinutes = time.minutes;
let nHours = time.hours;
nSeconds++;
if (nSeconds > 59) {
nMinutes++;
nSeconds = 0;
}
if (nMinutes > 59) {
nHours++;
nMinutes = 0;
}
if (nHours > 24) {
nHours = 0;
}
!isCancelled && setTime({ seconds: nSeconds, minutes: nMinutes, hours: nHours });
}, 1000);
};
advanceTime();
return () => {
//final time:
console.log(time);
isCancelled = true;
};
}, [time]);
return (
<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>
);
}
export default About;
时间.js
import React, { useState, useEffect } from 'react';
const Time = () => {
const [time, setTime] = useState({
seconds: 0,
minutes: 0,
hours: 0,
});
useEffect(() => {
let isCancelled = false;
const advanceTime = () => {
setInterval(() => {
let nSeconds = time.seconds;
let nMinutes = time.minutes;
let nHours = time.hours;
nSeconds++;
if (nSeconds > 59) {
nMinutes++;
nSeconds = 0;
}
if (nMinutes > 59) {
nHours++;
nMinutes = 0;
}
if (nHours > 24) {
nHours = 0;
}
!isCancelled && setTime({ seconds: nSeconds, minutes: nMinutes, hours: nHours });
}, 1000);
};
advanceTime();
return () => {
//final time:
console.log(time);
isCancelled = true;
};
}, [time]);
return (
<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>
);
}
export default Time;
应用程序.js
import React from 'react';
import logo from './logo.svg';
import './App.css';
import Nav from './component/Nav';
import About from './component/About';
import {BrowserRouter as Router, Switch, Route} from 'react-router-dom';
import Time from './component/Time';
function App() {
return (
<Router>
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<div>
<Nav />
<Switch>
<Route path = "/about" exact component = {About}/>
<Route path = "/time" exact component = {Time}/>
</Switch>
</div>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
</Router>
);
}
export default App;
解决方案
这只是您需要做的事情的要点。当您导航到另一条路线并返回时,组件将被重新渲染。正因为如此,他们的状态将不复存在。
要维护状态,您可以将您的状态“提升”到父组件。这意味着不是您About
和Time
组件管理它们自己的状态,而是管理它们的App
两个状态。
这看起来像这样:
function App() {
const [time, setTime] = useState({
seconds: 0,
minutes: 0,
hours: 0,
});
const [isAboutTimerOn, setIsAboutTimerOn] = useState(false)
const advanceTime = () => {
setIsAboutTimerOn(true)
setInterval(() => {
let nSeconds = time.seconds;
let nMinutes = time.minutes;
let nHours = time.hours;
nSeconds++;
if (nSeconds > 59) {
nMinutes++;
nSeconds = 0;
}
if (nMinutes > 59) {
nHours++;
nMinutes = 0;
}
if (nHours > 24) {
nHours = 0;
}
isAboutTimerOn && setTime({ seconds: nSeconds, minutes: nMinutes, hours: nHours });
}, 1000);
};
const startTime = () => {
advanceTime()
}
const stopTime = () => {
setIsAboutTimerOn(false)
}
return (
<Router>
<div className="App">
<Nav />
<Switch>
<Route path="/about" exact component={() => <About startTime={startTime} stopTime={stopTime} time={time}/>}/> // pass props
</Switch>
</div>
</Router>
);
}
您的用例的逻辑可能不正确,但问题与状态管理有关
由于您要管理两种不同的状态,因此您的代码将更加复杂。不过,您应该能够使你们中的一些逻辑可重用。
然后您的子组件将如下所示:
const About = ({ time, startTime, stopTime }) => {
useEffect(() => {
startTime()
return () => {
stopTime()
}
}, [startTime, stopTime])
return (
<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>
);
}
推荐阅读
- android - 如何使用 Retrofit 将大型 JSON 数据发送到服务器?
- cucumber - 黄瓜场景中的随机字符串
- python - 我如何在 TensorFlow 中开发深度稀疏自动编码器成本函数?
- regex - 如何使用 sed 正则表达式在特定单词之前添加一个新单词
- unity3d - Unity 碰撞后仅向用户添加一次点
- ghostscript - Ghotstscript 增加内容的长度
- assembly - 8085-进位标志的奇怪行为
- javascript - 离子未捕获错误:找不到模块“。” 导入服务提供者时
- html - CSS:使用引导程序 3 的表单控件对齐
- c# - C# & Razor:在 ASP.NET 中使用 HTML 表的动态日历