由于您的setInterval,您有内存泄漏。
每 1000 毫秒,它会重新运行,但同时,您的 useEffect 也被 setTimer(internal); 触发。所以你有越来越多的 setInterval 运行。
一种解决方案是在更新Timer 之前添加clearInterval(interval2);。
但从概念上讲它并不完美,因为我们使用间隔作为超时,因此您只需将 setInterval 替换为 setTimeout 并在返回 clearInterval 中替换为 clearTimeout 即可,无需修改任何其他内容。
这是您的代码经过修改的工作版本和sandbox:
import React from "react";
import PropTypes from "prop-types";
import { makeStyles } from "@material-ui/styles";
import { LinearProgress } from "@material-ui/core";
import { useEffect } from "react";
const TotalProfit = (props) => {
const [timer, setTimer] = React.useState(0);
useEffect(() => {
const interval2 = setTimeout(() => {
var internal = timer;
if (internal < 100) {
internal = internal - 1.695 * -1;
} else {
internal = internal - 100;
}
setTimer(internal);
}, 1000);
return () => clearTimeout(interval2);
}, [timer]);
return (
<div>
<div>{timer}</div>
<LinearProgress color="secondary" value={timer} variant="determinate" />
</div>
);
};
TotalProfit.propTypes = {
className: PropTypes.string
};
export default TotalProfit;
正如here 所解释的那样,浏览器分配给非焦点标签的资源较少,因此计时器可能是错误的。因此,给出的解决方案之一是使用在首次渲染组件时初始化的计时器。然后你使用 Date.now() 和你的第一次渲染时间之间的差异来获得你的间隔(模 100)(sandbox)。
import React, { useEffect, useState } from "react";
import PropTypes from "prop-types";
import { makeStyles } from "@material-ui/styles";
import { LinearProgress } from "@material-ui/core";
const TotalProfit = (props) => {
const [timer] = useState(Date.now()/1000);
const [delta, setDelta] = useState(0);
useEffect(() => {
const interval2 = setInterval(() => {
setDelta((Date.now()/1000 - timer) % 100);
}, 1000);
return () => clearInterval(interval2);
}, [timer]);
return (
<div>
<div>{delta}</div>
<LinearProgress color="secondary" value={delta} variant="determinate" />
</div>
);
};
TotalProfit.propTypes = {
className: PropTypes.string
};
export default TotalProfit;
否则,如果您的目标只是拥有一个加载器,您可以使用如图所示的 css 动画(稍作修改以获得与 js 相同的渲染)here:
body {margin: 0; padding: 0;}
@keyframes loader-animation {
0% {
width: 0%;
}
100% {
width: 100%;
left: 0%
}
}
.loader {
height: 5px;
width: 100%;
}
.loader .bar {
position: absolute;
height: 5px;
background-color: dodgerblue;
animation-name: loader-animation;
animation-duration: 3s;
animation-iteration-count: infinite;
animation-timing-function: ease-in-out;
}
<div class="loader">
<div class="bar"></div>
</div>