Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Countdown timer in react-native

Tags:

react-native

I want to countdown from 3 to 1 when a screen is loaded in react-native. I tried it with setTimeOut like this and it didn't work. What am I doing wrong here? How can I achieve this? When the screen is loaded, I want to show 3 =-> 2 ==> 1 with 1 second interval. Here is my code.

 constructor(props) {
        super(props);

        this.state = {
            timer: 3
        }
    }

    // componentDidMount 
    componentDidMount() {
        setTimeout(() => {
            this.setState({
                timer: --this.state.timer
            })
        }, 1000);
    }
like image 910
Shashika Avatar asked Aug 05 '18 15:08

Shashika


2 Answers

In your code setTimeout is called in componentDidMount and ComponetDidMount will be called once in whole component lifeCycle. So, the function within setTimeout will be called once only. i.e. just after the first render but upon successive render, the componentDidMount won't be called.

Solution to your problem can be:

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: if we unmount the component before clearInterval called, there is a memory leak because the interval that is set when we start and the timer is not stopped. React provides the componentWillUnmount lifecycle method as an opportunity to clear anything that needs to be cleared when the component is unmounted or removed.

I have created a custom hook called useCountDownTimer to use this functionality in a functional component. If interested please check this GitHub gist link

like image 100
Mohammed Ashfaq Avatar answered Sep 20 '22 17:09

Mohammed Ashfaq


Updated Hooks (using useEffect) version to countdown using setInterval in react-native:

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)
}, []);

use the state variable timerCount as: <Text>{timerCount}</Text>

like image 21
Rishabh Jain Avatar answered Sep 17 '22 17:09

Rishabh Jain