Setinterval in a React App

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

using setInterval and clearInterval to change counter in react app

Let me first say that i started learning react like 1 week ago and i
still have some doubt and this code may be really bad even if it
works, but i still want to help so this is the code.

The main problem here is that useState function is an async function and it doesn't update in real time your variable so in this case checking waterLevel value without useEffect will not work.

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

const App = () => {
const [waterLevel, setWaterLevel] = useState(0);
const [actionType, setActionType] = useState();

useEffect(() => {
const interval = setInterval(() => {
if (actionType == "increase" && waterLevel < 5)
setWaterLevel(waterLevel + 1);
if (actionType == "decrease" && waterLevel > 0)
setWaterLevel(waterLevel - 1);
}, 2000);
return () => clearInterval(interval);
}, [actionType, waterLevel]);

return (
<div>
<div>Bathtub</div>
<button onClick={() => setActionType("increase")}>
increaseWaterLevel
</button>
<button onClick={() => setActionType("decrease")}>
decreaseWaterLevel
</button>
<h1>{waterLevel}</h1>
</div>
);
};

export default App;

How to use setInterval in react?

Use callback function in setCounter function. As you are calling the state update in an async function. it's good practice to update the state based on the previous state.

const [counter, setCounter] = useState(10);
useEffect(() => {
let timer = setInterval(() => {
setCounter(counter => {
const updatedCounter = counter - 1;
if (updatedCounter === 0) {
setWordIndex(wordIndex + 1);
setLives(lives - 1);
life.play();
return 10;
}
return updatedCounter;
}); // use callback function to set the state

}, 1000);
return () => clearInterval(timer); // cleanup the timer
}, []);

why does my setInterval is not working in React app

Calling a functional component alone doesn't do anything unless you put the resulting element into a ReactDOM.render or into another functional component. Your setInterval(App, 1000); is doing nothing.

Have the component get itself to rerender instead.

function App() {
const [date, setDate] = useState(new Date());
useEffect(() => {
setInterval(() => {
setDate(new Date());
}, 1000);
}, []);
return (
<div>
<Clock date={date} />
</div>
);
}

Then the single use of ReactDOM.render(<App />, document.getElementById("root")); will result in the clock updating whenever the state changes.

If you ever plan on unmounting the component, it'd also be good to save the interval ID in a variable and return a cleanup function from the effect callback to clear the interval.

  useEffect(() => {
const intervalId = setInterval(() => {
setDate(new Date());
}, 1000);
return () => clearInterval(intervalId);
}, []);

setInterval behaving sporadically in React app

That's because you're using a functional component which is actually the render function of the component.

It's being executed every time you re-render the component, thus every time you change the state.

What you need is encapsulate it in a useEffect with an empty dependency array like this:

useEffect(() => setInterval(fetchLtcArbHandler, 5000), []);

Also, you need to return a cleanup function, otherwise the requests will run indefinitely even when the component is unmounted, while also causing a memory leak because of the potential closure context references:

useEffect(() => {
const interval = setInterval(fetchLtcArbHandler, 5000);
return () => clearInterval(interval);
}, []);


Related Topics



Leave a reply



Submit