React SetInterval Conflicts: How to Easily Resolve Them
Tags: react
Published: 2022-11-30 17:09:27

<figure><img src="https://d37oebn0w9ir6a.cloudfront.net/account_32099/setIntervalinreact_a83ff18b60993011bd7361ec648e522a.jpg" alt="Two people working at computers."/></figure>

Have you ever noticed React[ setInterval](https://developer.mozilla.org/en-US/docs/Web/API/setInterval) functions acting strangely? I’ve found that React Hooks can often help to fix `setInterval` problems.

In this article, I'll demonstrate how to use `setInterval` with React Hooks. However, it should be noted that the way `setInterval` works in Vanilla JavaScript is generally different.

## Overview of SetInterval 

At each specified timing event, the `setInterval()` React method repeats a block of code.

This is JavaScript's standard `setInterval` syntax:

```
setInterval(function, milliseconds);
```

Its qualities are:

- **Function**: The functions store executable code in a local scope.
- **Milliseconds**:  The milliseconds are a timer that triggers the function to execute a line of code.


We won't go into more detail in this React `setInterval` introduction. Instead, please refer to these [docs](https://developer.mozilla.org/en-US/docs/Web/API/setInterval)<u>.</u>

## Understanding the Effects of SetInterval on React Component Rendering

Every time the[ state](https://reactjs.org/docs/state-and-lifecycle.html) of a component changes, React prepares a render. This takes place once a render has been scheduled. React will look for the ideal time to do this. When we call the `setState` function in React, we are change the state, which results in an update (in React Hooks, we would use `useState`).

A component may re-render itself for one of four reasons: state changes, parent (or child) re-renderings,[ context](https://reactjs.org/docs/context.html) changes, and hook changes. A widespread misconception is that when the component's props change, re-renders likewise take place. On its own, this is untrue.

If React executes a[ component](https://reactjs.org/docs/react-component.html) more than once when using `setInterval` without a React Hook, the `SetInterval` will crash. If you use React and don't use the React Hook to build a counter increment mechanism with React `setInterval` in an initial page load, it will crash the counter. Therefore, we'll construct a counter increment in this tutorial using React Hooks.

### Bad Practices When Using SetInterval in React.js

Below is an example of the problem with utilizing `setInterval` in JavaScript without a React Hook:

**Bad Practice**

```
import { useState } from "react";
import { Fragment } from "react";

function App() {
 let [count, setCount] = useState(0);
 setInterval(() => {
  setCount(count + 1);
}, 2000);

return (
 <Fragment>
  <h1>Count: {count}</h1>
 </Fragment>
 );
}

export default App;
```

We can see that `setInterval` was not used in a React Hook in the code above, which is not best practice.

The code will be printed when the page loads for the first time, and along the way, the counter will begin to act improperly, which is not the best scenario.

## Resolving Conflicts in React.js

Next, we’ll be using `setInterval` with React Hooks in various ways.

In this section, we’ll be working with code samples and using a counter in React and a[ React Hook](https://reactjs.org/docs/hooks-overview.html).

### Using SetInterval in a Function-Based Component

Immediately after the page loads for the first time, we'll call `setInterval`.

Here, we'll make use of `setInterval` by automating its execution upon a page's initial load:

```
import { useEffect } from "react";
import { useState } from "react";
import { Fragment } from "react";

function App() {
 let [count, setCount] = useState({
  num: 0,
});

useEffect(() => {
 setInterval(() => {
 setCount((prevState) => {
  return {
   num: prevState.num + 1,
  };
 });
}, 1000);
}, []);

return (
 <Fragment>
  <div style={{ textAlign: "center" }}>
   <h1>Count: {count.num}</h1>
  </div>
 </Fragment>
);
}

export default App;
```

React Hooks like[ useState](https://reactjs.org/docs/hooks-state.html) and[ useEffect](https://www.google.com/search?q=react+useEffect&rlz=1C1ONGR_enNG1008NG1008&oq=react+useEffect&aqs=chrome..69i57j0i512l3j0i20i263i512j0i512j69i60l2.5344j0j4&sourceid=chrome&ie=UTF-8) were utilized in the code above.

The `useState` is dependent on its prior state:

```
setCount((prevState) => {
  return {
   num: prevState.num + 1,
  };
});
 useEffect(() => {
  setInterval(() => {
   setCount((prevState) => {
    return {
     num: prevState.num + 1,
   };
  });
 }, 1000);
}, []);
```

Output:

<figure><img src="https://d37oebn0w9ir6a.cloudfront.net/account_32099/image7_500c7375fc04ff89348244a79c76c3bb.png" alt="A count output."/></figure>

As you can see, the `useEffect` method, which has a return function, is used in the code above.

_The cleaning function (after the user exits the page and the component unmounts) is the return function._

When the app component loads for the first time, the `useEffect` hook wraps the `setState` counter to execute once. This stops React from entering an endless loop.

Kindly note that you can run the code without the cleanup return function. However, it's best practice to use it.

### Using setInterval in a React Class-based Component

Next, we’ll look at JavaScript `setInterval` in a class-based component in code below.

Furthermore, to start `setInterval` and stop crashes and errors, the `setInterval` is inserted inside the[ ComponentDidMount](https://reactjs.org/docs/react-component.html) component.

Read more about the React[ Lifecycle](https://reactjs.org/docs/state-and-lifecycle.html)<u>.</u>

Keep in mind that the interval begins as soon as a component loads for the first time. `UseEffect` is utilized in the function base component.

```
import React from "react";

class App extends React.Component {
 state = { count: 0 };
 componentDidMount() {
  setInterval(() => {
   this.setState((prevState) => {
    return {
     ...prevState,
    count: prevState.count + 1,
   };
  });
 }, 1000);
}

render() {
 return (
  <div>
   <h1>{this.state.count} Seconds</h1>
  </div>
 );
}
}

export default App;
```

Output:

<figure><img src="https://d37oebn0w9ir6a.cloudfront.net/account_32099/image1_fae1e6f6a2275037f169ca9c04b5e522.png" alt="The output of the above code, which is 2 seconds."/></figure>

### Calling React SetInterval from onClick in a Function-based Component

We can quickly use an `onClick` to call `setInterval`.

```
import { useState } from "react";

function App() {
 const [count, setCount] = useState(0);

const startCountHandler = () => {
 setInterval(() => {
  setCount((count) => count + 1);
 }, 1000);
};

return (
 <div style={{ textAlign: "center" }}>
  <h1>{count}</h1>
  <br />
  <button onClick={startCountHandler}>Start</button>
 </div>
);
}

export default App;
```

Output:

<figure><img src="https://d37oebn0w9ir6a.cloudfront.net/account_32099/image5_16d5b4cd954ec316c1688ca980ed7667.png" alt="The output of a React setInterval function; 551."/></figure>

### Using Clear Interval from an onClick in a Function-based Component

To stop the counter in this area, we'll use[ clearinterval](https://developer.mozilla.org/en-US/docs/Web/API/clearInterval). It is incredibly simple to use.

```
import { useState } from "react";

function App() {
 const [count, setCount] = useState(0);
 const [intervalId, setIntervalId] = useState(0);

const startCountHandler = () => {
 let newIntervalId = setInterval(() => {
  setCount((count) => count + 1);
}, 1000);

 setIntervalId(newIntervalId);
};

// Stopping the interval
const stopCountHandler = () => {
 clearInterval(intervalId);
};

return (
 <div style={{ textAlign: "center" }}>
  <h1>{count}</h1>
  <br />
  <button onClick={startCountHandler}>Start</button>
  <br />
  <button onClick={stopCountHandler}>Stop</button>
 </div>
);
}

export default App;
```

To store the interval id obtained from `setInterval`, a new state was made. The function for establishing the interval is activated when we click the start button, and we added `setIntervalId(newIntervalId)` inside the React `SetInterval` function to save the interval id in the state we generated for the `intervalID`.

Output:

<figure><img src="https://d37oebn0w9ir6a.cloudfront.net/account_32099/image2_528402bdf8649552a6a563bfbb958a3c.png" alt="A React setInterval component&#x27;s output: 14."/></figure>

We can start the counter by pressing the start button, and stop the counter by pressing the stop button. By hitting the start button once more, a paused counter can be started again.

### Starting SetInterval in a Class-based Component from onClick

In this part, we'll call `setInterval` from a class-based component's[ onClick](https://reactjs.org/docs/handling-events.html) event.

_Note: Take care to bind the ‘this’ keyword, or else you can’t access the_ `this.setState` _in the_ `startCountHandler` _function._

```
import React from "react";

class App extends React.Component {
 constructor(props) {
  super(props);
  this.state = { count: 0, intervalId: 0 };

 // Binfing this keyword
 this.startCountHandler = this.startCountHandler.bind(this);
}
startCountHandler() {
 setInterval(() => {
  this.setState((prevState) => {
   return {
    ...prevState,
    count: prevState.count + 1,
   };
  });
 }, 1000);
}

render() {
 return (
  <div>
   <h1>{this.state.count} Seconds</h1>
   <button onClick={this.startCountHandler}>Start</button>
  </div>
 );
}
}

export default App;
```

Output:

<figure><img src="https://d37oebn0w9ir6a.cloudfront.net/account_32099/image6_fa54be2aa4ad64ee632bf2eaf0d20d70.png" alt="A timer created with a setInterval component."/></figure>

### Stopping the Countdown in Class-based Components Using clearInterval

In this section, we'll utilize `clearInterval` in a class-based component to stop the counter from running during an `onClick` event.

Let's get going.

_The function that will stop or pause the counter increment will be the React_ `setInterval` _handler, to which we will bind the keyword "this."_[ Learn more about the “this” keyword](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this)_<u>.</u>_

The code for a class-based component is shown below.

```
import React, { useEffect, useState } from "react";

class App extends React.Component {
 constructor(props) {
  super(props);
  this.state = { count: 0, intervalId: 0 };

// Binding this keyword
this.startCountHandler = this.startCountHandler.bind(this);
this.stopCountHandler = this.stopCountHandler.bind(this);
}
startCountHandler() {
 let newIntervalId = setInterval(() => {
  this.setState((prevState) => {
   return {
    ...prevState,
    count: prevState.count + 1,
   };
});
}, 1000);

// Append the interval Id to state interval
this.setState((prevState) => {
 return {
  ...prevState,
  intervalId: newIntervalId,
 };
});
}

// Stopping the setInterval with clearinterval
stopCountHandler() {
 if (this.state.intervalId) {
  clearInterval(this.state.intervalId);
 }
}

render() {
 return (
  <div style={{ textAlign: "center" }}>
   <h1>{this.state.count} Seconds</h1>
   <button onClick={this.startCountHandler}>Start</button>
   <br />
   <button onClick={this.stopCountHandler}>Stop</button>
  </div>
 );
}
}

export default App;
```

Output:

<figure><img src="https://d37oebn0w9ir6a.cloudfront.net/account_32099/image4_aa4ac120590b8c621251fcb1e1794c75.png" alt="A timer with a start and a stop button."/></figure>

### Utilizing a Backward Counter

```
import { useState, useEffect } from 'react';

const ForwardCounter = () => {
 const [counter, setCounter] = useState(0);

useEffect(() => {
 const interval = setInterval(() => {
  setCounter((prevCounter) => prevCounter - 1);
 }, 1000);

 return () => clearInterval(interval);
}, []);

 return <h1>{counter}</h1>;
};

export default ForwardCounter;
```

The aforementioned code is a straightforward example of utilizing `setInterval` in a React Hook to interact with a backward counter.

Please be aware that using `setInterval` in a React Hook `useEffect` will cause the cleanup function to run.

### The Cleanup Function in useEffect

In this section, we'll demonstrate how to send a request to a fake server utilizing the[ useEffect cleanup function](https://reactjs.org/docs/hooks-effect.html) rather than while the user is still typing.

_The cleaning function, which runs after the user exits the page and the component unmounts, is the return function._

This greatly helps to avoid sending many requests while a user is typing, which would slow down our web app. Creating a search mechanism that returns a list of values from a server in this way is great practice.

Here, we'll implement this process using[ setTimeout](https://developer.mozilla.org/en-US/docs/Web/API/setTimeout) rather than `setInterval`.

Now, we’ll use [clearInterval](https://developer.mozilla.org/en-US/docs/Web/API/clearInterval) to do the cleanup operation. 

```
import { useEffect, useState } from "react";

function App() {
 const [enteredValue, setEnteredValue] = useState("");
useEffect(() => {
 const interval = setTimeout(() => {
  if (enteredValue.length > 0) {
  // Make a fetch request in a real project
  console.log("Send a request to a server...");
 }
}, 1000);

 return () => clearInterval(interval);
}, [enteredValue]);

const onChangedHandler = (e) => {
 setEnteredValue(e.target.value);
};

return (
 <div style={{ textAlign: "center" }}>
  <input
   type={"text"}
   onChange={onChangedHandler}
   value={enteredValue}
   style={{ padding: "10px", margin: "40px" }}
  />
 </div>
);
}

export default App;
```

Output: 

<figure><img src="https://d37oebn0w9ir6a.cloudfront.net/account_32099/image3_af7f215fe7c98c3870012aeed1efd176.png" alt="A photo of a console log."/></figure>

We can see from the output in the[ console](https://developer.mozilla.org/en-US/docs/Web/API/console) that the console log was produced four times, which indicates that I actually waited four times before inputting another character.

Make sure to test this out for yourself to see how it performs.

All I ask is that you start using this in your React project so that you discover its value.

## Conclusion

I hope you had a good time reading this article! We learned how to utilize React [setInterval](https://developer.mozilla.org/en-US/docs/Web/API/setInterval) and[ clearInterval](https://developer.mozilla.org/en-US/docs/Web/API/clearInterval) in class & function-based components without crashes and errors, as well as how React renders a component and affects `setInterval`. Start making changes to your app so that it takes advantage of the strategies we discussed in this post. Setting up `setInterval` in your program allows you to add more features and ensures that everything runs smoothly.