React-Native中的倒数计时器

时间:2018-08-05 15:55:14

标签: react-native

当屏幕以本机模式加载时,我想从3倒数到1。我像这样用setTimeOut尝试过,但是没有用。我在这里做错了什么?我该如何实现?加载屏幕时,我想以1秒的间隔显示3 =-> 2 ==> 1。这是我的代码。

 constructor(props) {
        super(props);

        this.state = {
            timer: 3
        }
    }

    // componentDidMount 
    componentDidMount() {
        setTimeout(() => {
            this.setState({
                timer: --this.state.timer
            })
        }, 1000);
    }

5 个答案:

答案 0 :(得分:11)

在您的代码中,在整个组件生命周期中,在c omponentDidMount 中调用setTimeout,并在一次中调用ComponetDidMount。因此,setTimeout中的函数将仅被调用一次。即在第一次渲染之后但在连续渲染之后,componentDidMount将不会被调用。

解决问题的方法可以是:

constructor(props: Object) {
  super(props);
  this.state ={ timer: 3}
}

componentDidMount(){
  this.interval = setInterval(
    () => this.setState((prevState)=> ({ timer: prevState.timer - 1 })),
    1000
  );
}

componentDidUpdate(){
  if(this.state.timer === 1){ 
    clearInterval(this.interval);
  }
}

componentWillUnmount(){
 clearInterval(this.interval);
}

render() {
  return (
    <View style={{ flex: 1, justifyContent: 'center', }}>
      <Text> {this.state.timer} </Text>
    </View> 
  )
}

'setInterval' vs 'setTimeout'

Advantage of using a function in setState instead of an object

memory leak because of setInterval: 如果在调用clearInterval之前卸载组件,则会发生内存泄漏,因为启动时设置的间隔和计时器未停止。 React提供了componentWillUnmount生命周期方法,作为清除在卸载或删除组件时需要清除的所有内容的机会。

答案 1 :(得分:2)

使用 setIntervalHooks(使用 useEffect)版本更新为 countdown反应原生:

const [timerCount, setTimer] = useState(60)

useEffect(() => {
  let interval = setInterval(() => {
    setTimer(lastTimerCount => {
        lastTimerCount <= 1 && clearInterval(interval)
        return lastTimerCount - 1
    })
  }, 1000) //each count lasts for a second
  //cleanup the interval on complete
  return () => clearInterval(interval)
}, []);

使用状态变量 timerCount 作为:<Text>{timerCount}</Text>

答案 2 :(得分:1)

钩子版本。

function CountDown() {
   const [count, setCount] = useState(3)

   useEffect(() => 
     let interval = setInterVal(() => {
        setCount(prev => {
           if(prev === 1) clearInterval(interval)
           return prev - 1
        })
     })
     // interval cleanup on component unmount
     return () => clearInterval(interval)
   ), [])

   return <Text>{count}</Text>
}

答案 3 :(得分:1)

如果有人想在按下按钮时再次启动计时器,这将是 react-hooks 中的代码:

let timer = () => {};

const myTimer = () => {
    const [timeLeft, setTimeLeft] = useState(30);

    const startTimer = () => {
        timer = setTimeout(() => {
            if(timeLeft <= 0){
                clearTimeout(timer);
                return false;
            }
         setTimeLeft(timeLeft-1);
        }, 1000)
     }

     useEffect(() => {
         startTimer();
         return () => clearTimeout(timer);
     });    

    const start = () => {
        setTimeLeft(30);
        clearTimeout(timer);
        startTimer();
    }

    return (
       <View style={styles.container}>
          <Text style={styles.timer}>{timeLeft}</Text>
          <Button onPress={start} title="Press"/>
    </View>
)}

在此示例中,我使用了 30 秒的计时器

答案 4 :(得分:0)

权力代码 希望这样很容易

  componentDidMount() {
        this.CounterInterval()
  }
  CounterInterval = () => {
    this.interval = setInterval(
      () =>   this.setState({
        timer: this.state.timer - 1
      }, () => {
        if (this.state.timer === 0) {
          clearInterval(this.interval);
        }
      }),
      1000
    );
  }