Javascript clearInterval不是清除间隔

Javascript clearInterval不是清除间隔,javascript,reactjs,Javascript,Reactjs,我知道这个问题已经被问了很多次了。。。但是我认为我做的一切都是正确的,它仍然不工作,clearInterval没有停止间隔,函数仍然每1秒被调用一次 这是我的全部代码: const [playerState, setPlayerState] = useState({ playing: true }); let [duration, setDuration] = useState(0); let counter = null; let count = () => {

我知道这个问题已经被问了很多次了。。。但是我认为我做的一切都是正确的,它仍然不工作,clearInterval没有停止间隔,函数仍然每1秒被调用一次

这是我的全部代码:

  const [playerState, setPlayerState] = useState({ playing: true });
  let [duration, setDuration] = useState(0);

  let counter = null; 
  let count = () => {
    setDuration(++duration);
  };

  let handlePlay = () => {
    setPlayerState({ playing: true });
    counter = setInterval(count, 1000); //call count every 1 second, working fine
    console.log("playing");
    console.log(duration);
  };

  let handlePause = () => {
    setPlayerState({ playing: false });
    clearInterval(counter);   // doesn't work the function is still being called  every 1 second.
    console.log("paused");
    console.log(duration);
  };
在调用handleplay时,持续时间应每1秒增加1,这很好,调用handlePause后,持续时间应停止增加,但不是这样!
感谢您回答当调用
handlePlay
时,它会调用
setPlayerState
。这会触发一个重新渲染器,从而产生一个新的
计数器
,其值为
null
。新的
handlePause
在该值周围有一个闭包。您可以尝试将计数器分配给state/ref。

问题是,每次调用组件函数来呈现组件(在任何一系列状态更改之后),都会创建一个新的
计数器
局部变量。存储计时器句柄的那个已不存在。您必须将计时器句柄保存在以后可以使用的地方(基本上是state或ref)。您还需要确保在组件卸载时有一个清除回调来取消计时器

见评论:

const [playerState, setPlayerState] = useState({ playing: true });
let [duration, setDuration] = useState(0);

// A ref to hold the timer handle
const timerRef = useRef(0);

// Register an unmount callback
useEffect(() => {
    // The return value is the clean up callback
    return () => {
        clearInterval(timerRef.current);
    };
}, []); // <== Empty dependency array means callback is called on unmount only

let count = () => {
    setDuration(++duration);
};

let handlePlay = () => {
    setPlayerState({ playing: true });
    // *** Use the ref
    clearInterval(timerRef.current);
    timerRef.current = setInterval(count, 1000); //call count every 1 second, working fine
    console.log("playing");
    console.log(duration);
};

let handlePause = () => {
    setPlayerState({ playing: false });
    // *** Use the ref
    clearInterval(timerRef.current);
    timerRef.current = 0;
    console.log("paused");
    console.log(duration);
};
const[playerState,setPlayerState]=useState({playing:true});
let[duration,setDuration]=useState(0);
//用于固定计时器手柄的ref
常数timerRef=useRef(0);
//注册一个卸载回调
useffect(()=>{
//返回值是清除回调
return()=>{
clearInterval(timerRef.current);
};
}, []); //  {
设置持续时间(++持续时间);
};
让handlePlay=()=>{
setPlayerState({playing:true});
//***使用ref
clearInterval(timerRef.current);
timerRef.current=setInterval(count,1000);//每1秒调用一次,工作正常
控制台日志(“播放”);
console.log(持续时间);
};
让handlePause=()=>{
setPlayerState({playing:false});
//***使用ref
clearInterval(timerRef.current);
timerRef.current=0;
控制台日志(“暂停”);
console.log(持续时间);
};

是的,这很有道理,我是新手,不知道useRef是如何工作的,我想我应该学习一下,谢谢。