考虑这段代码:
const [seconds, setSeconds] = useState<number>(START_VALUE);
useEffect(() => {
const intervalId = setInterval(() => {
setSeconds((previousSeconds) => previousSeconds - 1);
}, 1000);
if(seconds <= 0) {
clearInterval(intervalId);
functionX();
}
return () => clearInterval(intervalId);
}
}, [seconds]);
上述代码的问题是,每秒都会触发
useEffect
,有没有办法访问setSeconds
计算中的值以在setInterval
内部使用?
setInterval 调用在 useEffect 中打开。每次状态发生变化时都会调用它。因此它是无限的。
请为 setInterval 添加条件,以便仅调用一次。由于它是调度代码,因此应该只调用一次。一旦安排好,它就会自动按照时间表运行。
为了为 setInterval 设置条件,请使用 ref,如下面的代码所示。如您所知,即使在渲染后,Ref 仍将保留其值。因此,这里将是一个理想的选择。 有关 refs 的更多信息,请参阅此处 何时使用 refs
不需要 useEffect 的清理代码,因为 useEffect 中的自定义代码会处理它。清除设定的间隔。
App.js
import { useState, useEffect, useRef } from 'react';
const START_VAL = 3;
export default function App() {
const [seconds, setSeconds] = useState(START_VAL);
const intervalId = useRef(0);
useEffect(() => {
if (intervalId.current == 0) {
intervalId.current = setInterval(() => {
setSeconds((previousSeconds) => previousSeconds - 1);
}, 1000);
} else if (seconds === 0) {
clearInterval(intervalId.current);
}
}, [seconds]);
return `${seconds} of ${START_VAL} seconds`;
}
试运行
组件总共渲染了4次。
// 3 of 3 seconds
// 2 of 3 seconds
// 1 of 3 seconds
// 0 of 3 seconds