【发布时间】:2020-06-16 15:54:46
【问题描述】:
我在 react 中写了一个简单的秒表。
为了每秒渲染新的数字,我使用了 setInterval:
import React, {useEffect, useState, useRef} from 'react';
const MAX_TIMER = 5;
export default function StopWatch() {
const [timer, setTimer] = useState(0);
const tickIntervalId = useRef(null);
const tickTimer = (getTimerTimeFn) => {
const number = getTimerTimeFn();
setTimer(number);
if(number === MAX_TIMER) {
clearInterval(tickIntervalId.current);
}
}
let i = 0;
console.log('i is: ', i) // i value is 0 every render
const incrementNumber = () => {
i += 1;
console.log('in incrementNumber, i is: ', i); // i value is incrementing every render: 1, 2, 3, 4, 5. how?
return i;
}
useEffect(() => {
tickIntervalId.current = setInterval(tickTimer, 1000, incrementNumber);
}, [])
return (
<div>
{timer}
</div>
);
}
问题是 - 为什么这款秒表能按预期工作?
由于每一秒我都会重新渲染组件,所以let i = 0 行会再次执行,所以我希望
incrementNumber 的返回值将始终为 1 (0 + 1)
但相反,返回的值是递增的:1,2,3,4,5。
这是控制台输出:
i is: 0
in incrementNumber, i is: 1
i is: 0
in incrementNumber, i is: 2
i is: 0
in incrementNumber, i is: 3
i is: 0
in incrementNumber, i is: 4
i is: 0
in incrementNumber, i is: 5
i is: 0
【问题讨论】:
-
将
i和incrementNumber声明移动到全局范围。 -
代码正在运行,您可以从我附加的代码沙箱中看到。问题不在于如何让它发挥作用。
-
@Ido 您在函数范围之外声明变量
i,因此每次调用它都会递增。如果您在函数incrementNumber中声明i,它将始终重新初始化为零。那是你的问题吗?i实际上是StopWatch()的成员 -
@DanielB.Chapman 这不是问题,问题是
i怎么可能在incrementNumber函数内不断增加,即使i没有存储在状态中,而你甚至可以在控制台输出中看到i在每次渲染时都设置为 0。 -
@Ido 这是一个词法作用域问题,这就是为什么将
i和incrementNumber移动到全局作用域会破坏它。
标签: javascript reactjs setinterval