正如其他人所指出的,问题在于只调用一次(as)来设置间隔:useState
deps = []
React.useEffect(() => {
const timer = window.setInterval(() => {
setTime(time + 1);
}, 1000);
return () => window.clearInterval(timer);
}, []);
然后,每次价格变动时,它实际上都会调用 ,但将始终保持定义回调(闭包)时最初具有的值。setInterval
setTime(time + 1)
time
setInterval
您可以使用 setter 的替代形式,并提供回调而不是要设置的实际值(就像 ):useState
setState
setTime(prevTime => prevTime + 1);
但是我鼓励你创建自己的钩子,这样你就可以通过使用声明性的方式来干燥和简化你的代码,正如Dan Abramov在Make setInterval Declarative with React Hooks中建议的那样:useInterval
setInterval
function useInterval(callback, delay) {
const intervalRef = React.useRef();
const callbackRef = React.useRef(callback);
// Remember the latest callback:
//
// Without this, if you change the callback, when setInterval ticks again, it
// will still call your old callback.
//
// If you add `callback` to useEffect's deps, it will work fine but the
// interval will be reset.
React.useEffect(() => {
callbackRef.current = callback;
}, [callback]);
// Set up the interval:
React.useEffect(() => {
if (typeof delay === 'number') {
intervalRef.current = window.setInterval(() => callbackRef.current(), delay);
// Clear interval if the components is unmounted or the delay changes:
return () => window.clearInterval(intervalRef.current);
}
}, [delay]);
// Returns a ref to the interval ID in case you want to clear it manually:
return intervalRef;
}
const Clock = () => {
const [time, setTime] = React.useState(0);
const [isPaused, setPaused] = React.useState(false);
const intervalRef = useInterval(() => {
if (time < 10) {
setTime(time + 1);
} else {
window.clearInterval(intervalRef.current);
}
}, isPaused ? null : 1000);
return (<React.Fragment>
<button onClick={ () => setPaused(prevIsPaused => !prevIsPaused) } disabled={ time === 10 }>
{ isPaused ? 'RESUME ⏳' : 'PAUSE