Advertisements
I am using setInterval
and clearInterval
in a React functional component. I am incrementing the count inside the setInterval
and want to clearInterval
once it has reached certain value.but it is not clearing out, not sure what I am doing wrong.
const { useState, useEffect } = React;
/*export default*/ function App() {
const [chartsCount, setChartsCount] = useState(1);
useEffect(() => {
const chartsCountId = setInterval(() => {
setChartsCount((count) => {
console.log('set chart count function is running ', { chartsCount });
if (chartsCount >= 3/*16*/) {
console.log('We have reached the limit');
clearInterval(chartsCountId);
}
return count + 1;
});
}, 1000);
return () => {
clearInterval(chartsCountId);
};
}, [chartsCount]);
return (
<div>
<h1>Hello StackBlitz!</h1>
<p>Start editing to see some magic happen :)</p>
</div>
);
}
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<App />);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>
>Solution :
The problem is that you’ve made chartsCount
a dependency on the useEffect
, so every time it changes one interval is canceled and another is started. But your code within the interval callback uses the old timer handle (the one that’s already been cancelled) instead of the new one when it reaches the limit.
Instead:
- Don’t make
chartsCount
a dependency of the effect, and - Use
count
(the parameter if yoursetChartsCount
callback) rather thanchartsCount
in your effect code
Updated snippet, see the three comments with ***
:
const { useState, useEffect } = React;
/*export default*/ function App() {
const [chartsCount, setChartsCount] = useState(1);
useEffect(() => {
const chartsCountId = setInterval(() => {
setChartsCount((count) => {
console.log('set chart count function is running ', { chartsCount: count }); // ***
if (count >= 3/*16*/) { // ***
console.log('We have reached the limit');
clearInterval(chartsCountId);
}
return count + 1;
});
}, 1000);
return () => {
clearInterval(chartsCountId);
};
}, []); // ***
return (
<div>
<h1>Hello StackBlitz!</h1>
<p>Start editing to see some magic happen :)</p>
</div>
);
}
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<App />);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>