Reactjs 如何在react with hooks中通过切换功能设置和清理间隔?

Reactjs 如何在react with hooks中通过切换功能设置和清理间隔?,reactjs,setinterval,react-hooks,clearinterval,Reactjs,Setinterval,React Hooks,Clearinterval,我正在尝试构建一个计时器开关,该开关由一个带有函数handleToggle的按钮触发,如下所示: const handleToggle = () => { let timer = () => setInterval(() => { dispatch({ type: "COUNT", payload: Date.now() - startTime }); }, 100); const startTime = Date.now() - AppSt

我正在尝试构建一个计时器开关,该开关由一个带有函数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

我正在努力停止计时器,如何清除计时器间隔? 我试过:


但是没有区别…

在您的示例中,对
intervalId
的引用在函数执行结束时丢失

您应该使用实例变量来存储intervalId。如果您有
组件,则可以使用以下代码:

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 });
}
如果您在
函数
组件中,则可以使用来获得相同的行为:

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
的返回值;在第一个示例中,您将自己的函数传递给它。第二个示例有此权利,但您正在将
计时器
(调用
setInterval
的结果)存储在toggle函数的范围内,这意味着一旦函数完成,您将丢失对它的引用;下次调用函数时(例如停止函数),您需要重新定义
计时器
,这不是您想要的

您所需要的只是将
计时器
变量保持在它将持续存在的范围内。例如:

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
中初始化了计时器。您可以使用带有钩子的
setInterval
查看Dan Abramov的博客帖子:
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 });
  }
};