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
Disable Hover Effects on Mobile Browsers
Background-Color Hex to JavaScript Variable
How to Use Blob Url, Mediasource or Other Methods to Play Concatenated Blobs of Media Fragments
Reason Behind This Self Invoking Anonymous Function Variant
Detect When User Accepts to Download a File
How to Convert Dataurl to File Object in JavaScript
JavaScript Ie Detection, Why Not Use Simple Conditional Comments
Dom Refresh on Long Running Function
Difference Between Dot Notation and Bracket Notation in JavaScript
Node.Js Async/Await Using with MySQL
Create a File Using JavaScript in Chrome on Client Side
Nested Element (Web Component) Can't Get Its Template