【发布时间】:2020-11-20 02:36:53
【问题描述】:
我使用 React 函数组件开发了一个时钟组件。因为我需要每秒刷新时钟。我用过 setTimeout。
我已使用“useState”将 setTimeout Id 存储为状态变量,稍后在卸载组件时用于清除计时器。
我在这里使用了状态而不是普通变量,因为后者将在每次组件呈现并且不维持最后分配的值时被初始化。
但令我沮丧的是,每次更新timeElement时,组件都会渲染两次,后来我发现当setTimeout Id在本地状态下更新时,组件又被渲染了一次.
您能告诉我如何避免重新渲染吗?
工作演示可用here
编辑: 许多人通过使用 setInterval 而不是 setTimeout 提供了解决方案。这很好,但仍然无法使用 setTimeout 本身来实现它吗?我们是否必须采用这种解决方案?
function ClockContainer() {
let [color, setColor] = React.useState(null);
let [show, setShow] = React.useState(true);
let displayBtnClickHandler = function () {
setShow(!show);
};
let onInputChangeHandler = function (orgEvent) {
setColor(orgEvent.target.value);
};
return (
<React.Fragment>
<button onClick={displayBtnClickHandler}>
{show ? "Hide" : "Show"}{" "}
</button>
{
show && <input
type="text"
placeholder="Enter Color"
onChange={onInputChangeHandler}
/>
}
{show ? <Clock color={color} /> : <h3>Clock Hidden!!</h3>}
</React.Fragment>
);
}
function Clock(props) {
let getTimer = function () {
let currentTime = new Date();
let hours = currentTime.getHours();
return {
currentTime,
hours,
minutes: currentTime.getMinutes(),
seconds: currentTime.getSeconds(),
ampm: hours >= 12 ? "pm" : "am"
};
};
let [timeElement, setTimeElements] = React.useState(getTimer());
let [updateTimer, setUpdateTimer] = React.useState(false);
let setTimer = function () {
clearTimeout(updateTimer);
let updateTimerlocal = setTimeout(() => {
setTimeElements(getTimer());
}, 1000);
setUpdateTimer(updateTimerlocal);
};
React.useEffect(() => {
console.log("Rendered");
});
React.useEffect(() => {
setTimer();
}, [timeElement]);
/* To call cleanup codes when destroyed useEffect with empty array needs to be passed */
React.useEffect(() => {
return function () {
console.log("UnMounted!!");
clearTimeout(setTimer);
};
}, []);
return (
<div className="clock" style={{ backgroundColor: props.color }}>
{timeElement.hours === 0
? 12
: timeElement.hours > 12
? timeElement.hours - 12
: timeElement.hours}
:
{timeElement.minutes > 9
? timeElement.minutes
: `0${timeElement.minutes}`}
:
{timeElement.seconds > 9
? timeElement.seconds
: `0${timeElement.seconds}`}{" "}
{timeElement.ampm}
</div>
);
}
ReactDOM.render(<ClockContainer />, document.getElementById("app"));
:root {
--firstColor: rgba(0, 169, 158, 1);
--secondColor: rgba(0, 191, 150, 1);
--textColor: #fff;
}
.clock {
position: relative;
border-radius: 0.5em;
margin: 10px auto;
font-family: "Open Sans", sans-serif;
text-align: center;
font-size: 29px;
color: var(--textColor);
line-height: 2em;
background: var(--firstColor);
width: fit-content;
padding: 10px 20px;
}
@media only screen and (min-width: 700px) and (max-width: 1000px) {
.clock {
font-size: 50px;
}
}
@media only screen and (min-width: 500px) and (max-width: 699px) {
.clock {
font-size: 45px;
}
}
@media only screen and (min-width: 200px) and (max-width: 499px) {
.clock {
font-size: 40px;
}
}
<div id=app></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
【问题讨论】:
标签: javascript html reactjs