setInterval in a React app
I see 4 issues with your code:
- In your timer method you are always setting your current count to 10
- You try to update the state in render method
- You do not use
setState
method to actually change the state - You are not storing your intervalId in the state
Let's try to fix that:
componentDidMount: function() { var intervalId = setInterval(this.timer, 1000); // store intervalId in the state so it can be accessed later: this.setState({intervalId: intervalId});},componentWillUnmount: function() { // use intervalId from the state to clear the interval clearInterval(this.state.intervalId);},timer: function() { // setState method is used to update the state this.setState({ currentCount: this.state.currentCount -1 });},render: function() { // You do not need to decrease the value here return ( <section> {this.state.currentCount} </section> );}
This would result in a timer that decreases from 10 to -N. If you want timer that decreases to 0, you can use slightly modified version:
timer: function() { var newCount = this.state.currentCount - 1; if(newCount >= 0) { this.setState({ currentCount: newCount }); } else { clearInterval(this.state.intervalId); }},
Updated 10-second countdown using class Clock extends Component
import React, { Component } from 'react';class Clock extends Component { constructor(props){ super(props); this.state = {currentCount: 10} } timer() { this.setState({ currentCount: this.state.currentCount - 1 }) if(this.state.currentCount < 1) { clearInterval(this.intervalId); } } componentDidMount() { this.intervalId = setInterval(this.timer.bind(this), 1000); } componentWillUnmount(){ clearInterval(this.intervalId); } render() { return( <div>{this.state.currentCount}</div> ); }}module.exports = Clock;
Updated 10-second countdown using Hooks (a new feature proposal that lets you use state and other React features without writing a class. They’re currently in React v16.7.0-alpha).
import React, { useState, useEffect } from 'react';import ReactDOM from 'react-dom';const Clock = () => { const [currentCount, setCount] = useState(10); const timer = () => setCount(currentCount - 1); useEffect( () => { if (currentCount <= 0) { return; } const id = setInterval(timer, 1000); return () => clearInterval(id); }, [currentCount] ); return <div>{currentCount}</div>;};const App = () => <Clock />;ReactDOM.render(<App />, document.getElementById('root'));