我正在构建一个简单的计时器应用程序,并使用钩子跟踪状态中经过的时间。我知道我正在正确设置状态,因为它每隔一秒就会显示在应用程序中。但是,当我控制台日志 elapsedTime
时,它会重复记录初始状态(在本例中为 0):
const Timer = () => {
const [elapsedTime, setElapsedTime] = React.useState(0);
const [totalTime, setTotalTime] = React.useState(0);
const handleStart = () => {
const startTime = Date.now();
setInterval(() => {
const et = Math.floor((Date.now() - startTime) / 1000);
setElapsedTime(et);
console.log(elapsedTime);
}, 1000);
};
const handleStop = () => {
clearInterval();
};
return (
<div className='container'>
<div className='timer'>
<div className='title'></div>
<div className='time'>{elapsedTime}</div>
<button onClick={handleStart}>Start</button>
<button onClick={handleStop}>Stop</button>
</div>
</div>
);
};
ReactDOM.render(<Timer />, document.getElementById("root"));
<div id="root"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
为什么我在第 9 行调用的 console.log
中没有反映我的状态变化?
答案 0 :(得分:2)
setState
是异步的,你不会看到函数作用域的变化
如果您想在放置 console.log
的地方查看新值,您只能执行 console.log(et);
您也可以使用useEffect
在控制台中查看变量的变化
useEffect(() => {
console.log("elapsedTime", elapsedTime);
}, [elapsedTime]);
答案 1 :(得分:1)
由于 javascript clojure,第 9 行的 elapsedTime
将始终引用它在创建函数时的值。
答案 2 :(得分:0)
您将如何停止计时器?
您必须引用您正在创建的计时器,以便您可以停止它。调用 setInverval
会返回这样的引用(唯一 ID)。
然后,您必须确保在任何时间点都只运行一个计时器。
借用 Marc Charpentier 的回答,您的代码的工作版本可能如下所示:
const Timer = () => {
const [elapsedTime, setElapsedTime] = React.useState(0);
const [totalTime, setTotalTime] = React.useState(0);
const [timerId, setTimerId] = React.useState();
React.useEffect(() => {
console.log("elapsedTime", elapsedTime);
}, [elapsedTime]);
const handleStart = () => {
const startTime = Date.now();
if (timerId === undefined) { // make sure that a timer is not already running
setTimerId(
setInterval(() => {
const et = Math.floor((Date.now() - startTime) / 1000);
setElapsedTime(et);
}, 1000)
);
}
};
const handleStop = () => {
clearInterval(timerId);
setTimerId(undefined);
};
return (
<div className='container'>
<div className='timer'>
<div className='title'></div>
<div className='time'>{elapsedTime}</div>
<button onClick={handleStart}>Start</button>
<button onClick={handleStop}>Stop</button>
</div>
</div>
);
};
ReactDOM.render(<Timer />, document.getElementById("root"));
<div id="root"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>