Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/477.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript setInterval和clearInterval不一起工作_Javascript_Reactjs_Redux - Fatal编程技术网

Javascript setInterval和clearInterval不一起工作

Javascript setInterval和clearInterval不一起工作,javascript,reactjs,redux,Javascript,Reactjs,Redux,所以我有一个setInterval和clearInterval函数来分别启动和停止计数器。这里的问题是,每次我单击按钮,状态都会设置为true,并且会触发timer函数,从而启动计时器。现在再次单击计时器,计时器不会停止,因为refreshIntervalId变量现在的值为undefined。请帮帮我 这是我的密码: if (timer == true) { console.log("timer is playing"); refreshIntervalID = setInt

所以我有一个setInterval和clearInterval函数来分别启动和停止计数器。这里的问题是,每次我单击按钮,状态都会设置为true,并且会触发timer函数,从而启动计时器。现在再次单击计时器,计时器不会停止,因为refreshIntervalId变量现在的值为undefined。请帮帮我

这是我的密码:

  if (timer == true) {
    console.log("timer is playing");
    refreshIntervalID = setInterval(timerFunction, 1000);
    console.log(refreshIntervalID);
  }

  if (timer == false) {
    console.log(refreshIntervalID);
    clearInterval(refreshIntervalID);
  }
以下是完整的代码:

import React from "react";
import "./App.css";
import { useSelector, useDispatch } from "react-redux";
import { playToggle, reset } from "./actions/indexAction";

function Timer() {
  const timer = useSelector((state) => state.timer);
  const sessionLength = useSelector((state) => state.sessionLength);

  let minutes = sessionLength;
  let seconds = 60;
  var refreshIntervalID;

  const dispatch = useDispatch();

  let resetClick = () => {
    return dispatch(reset());
  };

  let timerFunction = () => {
    if (timer == true) {
      seconds--;
      console.log(seconds);
    }
  };

  if (timer == "reset") {
    minutes = sessionLength;
    seconds = 60;
    console.log("Is Reset");
  }

  if (timer == true) {
    console.log("timer is playing");
    refreshIntervalID = setInterval(timerFunction, 1000);
    console.log(refreshIntervalID);
  }

  if (timer == false) {
    console.log(refreshIntervalID);
    clearInterval(refreshIntervalID);
  }

  return (
    <div>
      <h1>Minutes: {minutes}</h1>
      <h1>Minutes: {seconds}</h1>
      <div>
        <button onClick={() => dispatch(playToggle())}>PLAY/PAUSE</button>
      </div>
      <div>
        <button onClick={resetClick}>RESET</button>
      </div>
    </div>
  );
}

export default Timer;
从“React”导入React;
导入“/App.css”;
从“react-redux”导入{useSelector,useDispatch};
从“/actions/indexAction”导入{playtogle,reset}”;
函数计时器(){
常量计时器=使用选择器((状态)=>state.timer);
const sessionLength=useSelector((state)=>state.sessionLength);
分钟=会话长度;
设秒=60;
有效期;
const dispatch=usedpatch();
让我们点击=()=>{
返回调度(reset());
};
let timer函数=()=>{
如果(计时器==真){
秒--;
console.log(秒);
}
};
如果(计时器=“重置”){
分钟=会话长度;
秒=60;
控制台日志(“被重置”);
}
如果(计时器==真){
log(“计时器正在播放”);
refreshIntervalID=setInterval(timerFunction,1000);
console.log(refreshIntervalID);
}
如果(计时器==false){
console.log(refreshIntervalID);
clearInterval(refreshIntervalID);
}
返回(
分钟:{Minutes}
分钟:{秒}
调度(播放切换())}>播放/暂停
重置
);
}
导出默认定时器;

这并不完全相关,因为与之相关的评论结果并不完全准确:

你绝对不想在redux reducer中产生副作用。让副作用发生在组件中。原因是,为了使整个通量结构正常工作,减速器应该是纯的。在reducer中唯一应该出现副作用的时候是如果您使用的是类似的中间件。否则,您很快就会得到一些无法维护的代码

如果这是在一个功能组件中,我是这样做的:

function(){
  useEffect(()=>{
    if (timer) {
      console.log("timer is playing");
      const refreshIntervalID = setInterval(timerFunction, 1000);
      console.log(refreshIntervalID);
      return ()=>{
        clearInterval(refreshIntervalID)
      }
    }
  },[timer])
}
您必须清除useEffect挂钩中的间隔

编辑:添加工作代码

import React, { useEffect, useState } from 'react';
import './App.css';
import { useSelector, useDispatch } from 'react-redux';
import { playToggle } from './actions/indexAction';

function Timer() {
  const timer = useSelector((state) => state.timer);
  const sessionLength = useSelector((state) => state.sessionLength * 60); // session in seconds
  const [seconds, setSeconds] = useState(sessionLength);
  const [resetTimer, setResetTimer] = useState(0);

  const dispatch = useDispatch();

  let resetClick = () => {
    // Get a new value every time
    setSeconds(sessionLength);
    setResetTimer((value) => value + 1);
  };
  useEffect(()=>{
    // Set the timer to use the latest value when the session length changes.
    setSeconds(sessionLength)
  },[sessionLength])

  useEffect(() => {
    // Perform a side effect
    if (timer) {
      // Only run the timer when timer is truthy
      let timerFunction = () => {
        setSeconds((seconds) => seconds - 1);
      };
      console.log('timer is playing');
      const refreshIntervalID = setInterval(timerFunction, 1000);
      return () => {
        // Clean up timer before effect runs again (or on unmount)
        clearInterval(refreshIntervalID);
      };
    }
    // Restart timer whenever timer, sessionLength, or resetTimer changes
  }, [timer, resetTimer]);

  useEffect(() => {
    // If the timer has elapsed, stop the timer and reset.
    if (seconds <= 0) {
      dispatch(playToggle());
      setSeconds(sessionLength);
    }
  }, [seconds, dispatch, sessionLength]);

  return (
    <div>
      <h1>Minutes: {Math.floor(seconds / 60)}</h1>
      <h1>Minutes: {seconds % 60}</h1>
      <div>
        <button onClick={() => dispatch(playToggle())}>PLAY/PAUSE</button>
      </div>
      <div>
        <button onClick={resetClick}>RESET</button>
      </div>
    </div>
  );
}

export default Timer;
import React,{useffect,useState}来自“React”;
导入“/App.css”;
从“react-redux”导入{useSelector,useDispatch};
从“./actions/indexAction”导入{playtokle};
函数计时器(){
常量计时器=使用选择器((状态)=>state.timer);
const sessionLength=useSelector((state)=>state.sessionLength*60);//以秒为单位的会话
常量[秒,设置秒]=使用状态(会话长度);
常量[resetTimer,setResetTimer]=useState(0);
const dispatch=usedpatch();
让我们点击=()=>{
//每次都获取一个新值
设置秒(会话长度);
setResetTimer((值)=>值+1);
};
useffect(()=>{
//将计时器设置为在会话长度更改时使用最新值。
设置秒(会话长度)
},[sessionLength])
useffect(()=>{
//产生副作用
中频(定时器){
//仅在计时器为真时运行计时器
let timer函数=()=>{
设置秒((秒)=>秒-1);
};
log(“计时器正在播放”);
const refreshIntervalID=setInterval(timerFunction,1000);
return()=>{
//在效果再次运行之前(或卸载时)清除计时器
clearInterval(refreshIntervalID);
};
}
//每当计时器、会话长度或重置计时器更改时,重新启动计时器
},[timer,resetTimer]);
useffect(()=>{
//如果计时器已过,请停止计时器并重置。
如果(秒)播放/暂停
重置
);
}
导出默认定时器;

您在何处声明
refreshIntervalID
?您需要对其进行作用域设置,以便
clearTimer
调用可以访问它。因此,作用域存在于redux reducer中。问题是,当我尝试给出一个状态时,它会抛出许多错误。我将上载整个文件供您查看。谢谢您的回答。我很抱歉对于我应该如何在代码中实现函数仍然感到困惑。我是一个初学者,如果您能帮助我,那将是非常棒的。我已经附上了我的完整代码供您参考。我已经重构了您的代码,并添加了一些基本的注释。希望这会有所帮助!如果您有任何问题,请告诉我。您必须从Rea导入它们作为参考,更新代码的第一行。很抱歉,这是一个打字错误。秒(应该设置为秒)(在那一行。我在回答中更新了它。如果还有其他类似的事情,请继续,为我们设置一个聊天,而不是一个评论线程。嗨,非常感谢你的帮助!工作非常完美。现在,我所要做的就是彻底理解代码。我几乎要放弃了,但你的解决方案让我回到了正轨。所以,谢谢你又来了!