This tutorial will show you how to run the setInterval()
method as soon as your component is mounted (rendered) on the screen or when a button is clicked by the user.
This tutorial uses React class component for its code examples. For the function component equivalent, you can refer to this tutorial:
How to use setInterval() method inside React components
Let’s begin with starting the interval when the component is mounted.
React class component, calling setInterval() on mount
To start the interval as soon as the class component has been rendered on the screen, you need to call the setInterval()
method inside the componentDidMount()
lifecycle method.
Here’s a pattern for using the setInterval()
method:
componentDidMount() {
setInterval(() => {
/*
Run any function or setState here
*/
}, 1000);
}
You can call the this.setState()
method inside the setInterval()
method to increment a previous state property value.
The following example uses the state property count
value as a timer that counts how many seconds have passed since the component has been rendered on the screen:
class App extends React.Component {
state = { count: 0 };
componentDidMount() {
const intervalId = setInterval(() => {
this.setState(prevState => {
return {
count: prevState.count + 1,
};
});
}, 1000);
}
componentWillUnmount(){
clearInterval(intervalId);
}
render() {
return (
<h1>The component has been rendered for {this.state.count} seconds</h1>
);
}
}
export default App;
The value of the count
property above will be incremented by 1 every 1000 milliseconds.
To stop the interval when the component is destroyed, you need to call the clearInterval()
method from inside the componentWillUnmount()
lifecycle method.
First, you need add a new property to the state object named intervalId
and set the initial value to 0
:
state = { count: 0, intervalId: 0 };
Next, save the interval ID returned from the setInterval()
method as the intervalId
state value.
The complete code for the componentDidMount()
method is as follows:
componentDidMount() {
const newIntervalId = setInterval(() => {
this.setState(prevState => {
return {
...prevState,
count: prevState.count + 1,
};
});
}, 1000);
this.setState(prevState => {
return {
...prevState,
intervalId: newIntervalId,
};
});
}
Although it looks complicated, the additional code only calls the setState()
method to assign the newIntervalId
value as the state.intervalId
value.
The prevState
value is expanded on the new state returned from the setState()
method so that the count
property won’t be removed from the state itself.
And that’s how to clear the interval before unmounting the component. Now let’s see how you can start and stop the interval method from a button click.
React class component, calling setInterval() on button click
To start the setInterval()
method when the user clicks on a button, you need to put the setInterval()
method call inside the button’s onClick
event handler property.
In essence, you only need to place the code inside the componentDidMount()
method above as the code you run when the button is clicked.
Take a look at the following code:
class App extends React.Component {
state = { count: 0, intervalId: 0 };
handleClick = () => {
const newIntervalId = setInterval(() => {
this.setState(prevState => {
return {
...prevState,
count: prevState.count + 1,
};
});
}, 1000);
this.setState(prevState => {
return {
...prevState,
intervalId: newIntervalId,
};
});
}
render() {
return (
<div>
<h1>The component has been rendered for {this.state.count} seconds</h1>
<button onClick={this.handleClick}>Start counter</button>
</div>
);
}
}
export default App;
To stop the interval, you need to add an if
block inside the handleClick()
method above.
If the state.intervalId
value is not zero (truthy) then you need to do the following steps:
- Call the
clearInterval()
method passing thestate.intervalId
as its argument - Call the
setState()
method and set theintervalId
value back to0
- Stop executing the
handleClick()
method by using thereturn
statement
Here’s the code implementing the above steps:
handleClick = () => {
if(this.state.intervalId){
clearInterval(this.state.intervalId);
this.setState(prevState => {
return {
...prevState,
intervalId: 0,
};
});
return;
}
const newIntervalId = setInterval(() => {
this.setState(prevState => {
return {
...prevState,
count: prevState.count + 1,
};
});
}, 1000);
this.setState(prevState => {
return {
...prevState,
intervalId: newIntervalId,
};
});
}
Don’t forget to update the button’s label to Start counting
or Stop counting
depending on the state.intervalId
value:
<button onClick={this.handleClick}>
{this.state.intervalId? "Stop counter": "Start counter"}
</button>
The full code for the class component is as shown below:
class App extends React.Component {
state = { count: 0, intervalId: 0 };
handleClick = () => {
if(this.state.intervalId){
clearInterval(this.state.intervalId);
this.setState(prevState => {
return {
...prevState,
intervalId: 0,
};
});
return;
}
const newIntervalId = setInterval(() => {
this.setState(prevState => {
return {
...prevState,
count: prevState.count + 1,
};
});
}, 1000);
this.setState(prevState => {
return {
...prevState,
intervalId: newIntervalId,
};
});
}
render() {
return (
<div>
<h1>The component has been rendered for {this.state.count} seconds</h1>
<button onClick={this.handleClick}>
{this.state.intervalId? "Stop counter": "Start counter"}
</button>
</div>
);
}
}
export default App;
And that’s how you can call the setInterval()
method with a button click inside a React class component.