如何通过切换功能设置和清理间隔以与钩子反应?
How to set and clean interval by toggle function in react with hooks?
我正在尝试构建一个计时器 由具有 handleToggle 功能的一个按钮触发,看起来像:
const handleToggle = () => {
let timer = () => setInterval(() => {
dispatch({ type: "COUNT", payload: Date.now() - startTime });
}, 100);
const startTime = Date.now() - AppState.runningTime;
if (AppState.countingStarted) {
dispatch({
type: "COUNTING_STARTED",
payload: false
});
clearInterval(timer());
} else {
timer()
dispatch({ type: "COUNTING_STARTED", payload: true });
}
};
COUNTING_STARTED 是一个调度函数,它切换 AppState.countingStarted.
我正在努力停止计时器,如何清除计时器间隔?
我试过了:
const handleToggle = () => {
let timer;
if (AppState.countingStarted) {
dispatch({
type: "COUNTING_STARTED",
payload: false
});
clearInterval(timer);
} else {
timer = setInterval(() => {
dispatch({ type: "COUNT", payload: Date.now() - startTime });
}, 100);
const startTime = Date.now() - AppState.runningTime;
dispatch({ type: "COUNTING_STARTED", payload: true });
}
};
但是没有区别...
在您的示例中,对 intervalId
的引用在函数执行结束时丢失。
您应该使用实例变量来存储 intervalId。如果您有 Class
组件,您可以使用以下代码:
handleToggle = () => {
// clear the interval, no matter the value of AppState.countingStarted
// this prevent from recreating the interval multiple times
clearInterval(this.timerId);
if (AppState.countingStarted) {
dispatch({type: "COUNTING_STARTED",payload: false});
} else {
// store the timer id in an instance variable
this.timerId = setInterval(() => {
dispatch({ type: "COUNT", payload: Date.now() - startTime });
}, 100);
dispatch({ type: "COUNTING_STARTED", payload: true });
}
如果您在 Function
组件中,您可以使用 hook useRef 获得相同的行为:
const timerIdRef = useRef(null);
const handleToggle = () => {
clearInterval(timerIdRef.current);
if (AppState.countingStarted) {
dispatch({type: "COUNTING_STARTED",payload: false});
} else {
// store the interval id into the current property
timerIdRef.current = setInterval(() => {
dispatch({ type: "COUNT", payload: Date.now() - startTime });
}, 100);
dispatch({ type: "COUNTING_STARTED", payload: true });
}
一些事情:你传递给 clearInterval
的东西必须是来自 setInterval
的 return 值;在第一个示例中,您将自己的函数传递给它。第二个例子有这个权利,但是你在切换函数的范围内存储 timer
(调用 setInterval
的结果),这意味着一旦函数完成,你就失去了对它的引用;下次调用该函数(例如停止它)时,您重新定义了 timer
,这不是您想要的。
您所需要的只是将 timer
变量保持在它会持续存在的范围内。例如:
let timer = null;
const handleToggle = () => {
if (AppState.countingStarted) {
dispatch({
type: "COUNTING_STARTED",
payload: false
});
clearInterval(timer);
} else {
timer = setInterval(() => {
dispatch({ type: "COUNT", payload: Date.now() - startTime });
}, 100);
const startTime = Date.now() - AppState.runningTime;
dispatch({ type: "COUNTING_STARTED", payload: true });
}
};
该函数可以多次调用; timer
变量将始终存在。
我正在尝试构建一个计时器 由具有 handleToggle 功能的一个按钮触发,看起来像:
const handleToggle = () => {
let timer = () => setInterval(() => {
dispatch({ type: "COUNT", payload: Date.now() - startTime });
}, 100);
const startTime = Date.now() - AppState.runningTime;
if (AppState.countingStarted) {
dispatch({
type: "COUNTING_STARTED",
payload: false
});
clearInterval(timer());
} else {
timer()
dispatch({ type: "COUNTING_STARTED", payload: true });
}
};
COUNTING_STARTED 是一个调度函数,它切换 AppState.countingStarted.
我正在努力停止计时器,如何清除计时器间隔? 我试过了:
const handleToggle = () => {
let timer;
if (AppState.countingStarted) {
dispatch({
type: "COUNTING_STARTED",
payload: false
});
clearInterval(timer);
} else {
timer = setInterval(() => {
dispatch({ type: "COUNT", payload: Date.now() - startTime });
}, 100);
const startTime = Date.now() - AppState.runningTime;
dispatch({ type: "COUNTING_STARTED", payload: true });
}
};
但是没有区别...
在您的示例中,对 intervalId
的引用在函数执行结束时丢失。
您应该使用实例变量来存储 intervalId。如果您有 Class
组件,您可以使用以下代码:
handleToggle = () => {
// clear the interval, no matter the value of AppState.countingStarted
// this prevent from recreating the interval multiple times
clearInterval(this.timerId);
if (AppState.countingStarted) {
dispatch({type: "COUNTING_STARTED",payload: false});
} else {
// store the timer id in an instance variable
this.timerId = setInterval(() => {
dispatch({ type: "COUNT", payload: Date.now() - startTime });
}, 100);
dispatch({ type: "COUNTING_STARTED", payload: true });
}
如果您在 Function
组件中,您可以使用 hook useRef 获得相同的行为:
const timerIdRef = useRef(null);
const handleToggle = () => {
clearInterval(timerIdRef.current);
if (AppState.countingStarted) {
dispatch({type: "COUNTING_STARTED",payload: false});
} else {
// store the interval id into the current property
timerIdRef.current = setInterval(() => {
dispatch({ type: "COUNT", payload: Date.now() - startTime });
}, 100);
dispatch({ type: "COUNTING_STARTED", payload: true });
}
一些事情:你传递给 clearInterval
的东西必须是来自 setInterval
的 return 值;在第一个示例中,您将自己的函数传递给它。第二个例子有这个权利,但是你在切换函数的范围内存储 timer
(调用 setInterval
的结果),这意味着一旦函数完成,你就失去了对它的引用;下次调用该函数(例如停止它)时,您重新定义了 timer
,这不是您想要的。
您所需要的只是将 timer
变量保持在它会持续存在的范围内。例如:
let timer = null;
const handleToggle = () => {
if (AppState.countingStarted) {
dispatch({
type: "COUNTING_STARTED",
payload: false
});
clearInterval(timer);
} else {
timer = setInterval(() => {
dispatch({ type: "COUNT", payload: Date.now() - startTime });
}, 100);
const startTime = Date.now() - AppState.runningTime;
dispatch({ type: "COUNTING_STARTED", payload: true });
}
};
该函数可以多次调用; timer
变量将始终存在。