发布
社区首页 >问答首页 >连续运行两个倒计时器。第二个被跳过。

连续运行两个倒计时器。第二个被跳过。
EN

Stack Overflow用户
提问于 2021-05-22 12:45:36
回答 1查看 306关注 0票数 1

我已经创建了一个叫做Timer的功能组件。我想运行一个3秒的计时器,然后运行一个6秒的计时器。然而,第二个定时器一开始就停止了。

我认为问题在于,第二个定时器正在使用来自第一个定时器的状态值。我不知道为什么会这样。我假设第二个定时器是一个新实例,所以它不应该与第一个计时器有任何链接。

这是我的密码:

代码语言:javascript
代码运行次数:0
复制
import React, { useEffect, useState } from 'react';
    
function App() {
  const [timer1Up, setTimer1Up] = useState(false);
  const [timer2Up, setTimer2Up] = useState(false);
  if(!timer1Up) {
    return <Timer duration={3} setTimeUp={setTimer1Up}/>
  }
  if(timer1Up && !timer2Up) {
    return <Timer duration={6} setTimeUp={setTimer2Up}/>
  }
  if(timer1Up && timer2Up) {
    return <>Out of all your time buddy!!</>
  }
  return <>I have no purpose</>;
}

interface TimerProps {
  duration: number;
  setTimeUp: any;
}

const Timer = (props: TimerProps) => {
  const [timeLeft, setTimeLeft] = useState(props.duration);
  useEffect(() => {
    setTimeout(() => {
      setTimeLeft(timeLeft - 1);
    }, 1000);
    if(timeLeft === 0) {
      props.setTimeUp(true);  
    }
  });
  return <>{timeLeft} s</>
}

export default App;
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-05-22 13:00:47

代码语言:javascript
代码运行次数:0
复制
if(!timer1Up) {
  return <Timer duration={3} setTimeUp={setTimer1Up}/>
}
if(timer1Up && !timer2Up) {
  return <Timer duration={6} setTimeUp={setTimer2Up}/>
}

react使用的主要方式是根据组件的类型判断它是需要挂载新组件还是重用现有组件。第一次呈现时,您将返回一个<Timer>,因此react将挂载一个新的计时器组件,然后开始进行倒计时。一旦完成了第一个倒计时,您将再次呈现,也会返回一个<Timer>。因此,据反应所知,唯一改变的是定时器上的道具。React保持相同的组件安装,具有相同的状态。

因此有两个选择: 1)强迫它重新安装;2)如果它的道具改变,让计时器重置。

为了迫使它重新装入,您需要使用键来明确地反应这些是不同的元素。这样,它将卸载旧计时器并装入一个新计时器,而新计时器可以有自己的状态来计数。

代码语言:javascript
代码运行次数:0
复制
if(!timer1Up) {
  return <Timer key="first" duration={3} setTimeUp={setTimer1Up}/>
}
if(timer1Up && !timer2Up) {
  return <Timer key="second" duration={6} setTimeUp={setTimer2Up}/>
}

要使它与改变道具一起工作,您需要添加逻辑来重置倒计时。您必须决定应该重置倒计时的条件,但有一个选项是,无论何时持续时间发生变化,您都可以重新开始:

代码语言:javascript
代码运行次数:0
复制
const Timer = (props: TimerProps) => {
  const [timeLeft, setTimeLeft] = useState(props.duration);
  useEffect(() => {
    setTimeLeft(props.duration);
    const intervalId = setInterval(() => {
      setTimeLeft(prev => {
        const next = prev -1;
        if (next === 0) {
          clearInterval(intervalId);
          // Need to slightly delay calling props.setTimeUp, because setting
          //    state in a different component while in the middle of setting
          //    state here can cause an error
          setTimeout(() => props.setTimeUp(true));
        }
        return next;
      });
    }, 1000);

    return () => { clearInterval(intervalId); }
  }, [props.duration]); // <---- dependency array to reset when the duration changes

  return <>{timeLeft} s</>
}

有关react如何决定挂载/卸载组件的更多信息,请参见这一页是关于和解的

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67649614

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档