通过一个变量来控制页面逻辑轮询,可以开启轮询,满足特定条件结束轮询,一般大家第一个想到的就是 setInterval
setInterval() 方法会不停地调用函数,直到 clearInterval() 被调用或窗口被关闭。由 setInterval() 返回的 ID 值可用作 clearInterval() 方法的参数
第一种方案
定时器正常启动,但是 clearInterval() 之后轮询依然没有停止
原因: 直接定义变量的话,改变这个变量,组件不会重新渲染,定时器清除了,但是页面上的轮询还在继续,看起来像是清除失败
let foo = null;
useEffect(() => {
if (view) {
foo = setInterval(() => {
// do someting
}, 2000);
} else {
clearInterval(foo);
foo = null
}
}, [view]);
最终解决方案
将变量保存在 state 中,使用一个变量来控制轮询的启动暂停
state跟上边的直接定义变量的区别:
setState 是异步执行的,当 setState 方法被调用后,方法会将状态传递给组件更新器,让组件更新器将状态临时存储起来,状态临时保存完成后判断当前是否为批量更新模式,如果是,将组件更新器添加到更新队列中;如果不是,直接更新组件
const [foo, setFoo] = useState(null);
useEffect(() => {
if (view) {
setFoo(setInterval(() => {
// do someting
}, 2000));
} else if (foo) {
clearInterval(foo);
setFoo(null);
}
}, [view]);
补充 useEffect 的执行周期
useEffect 没有第二个参数的时候,组件初始化及更新都会执行
useEffect(() => {
// do someting
});
useEffect 第二个参数为空数组时,仅在组件初始化时调用一次
useEffect(() => {
// do someting
}, []);
useEffect 第二个参数有一个或多个值时,其中值有变化就执行,多个值经过比较只要有一个变化就执行
useEffect(() => {
// do someting
}, [params1, params2]);