I am trying to create a loading component that will add a period to a div periodically, every 1000ms using setInterval in React. I am trying to cleanup setInterval using the method described in the docs.
https://reactjs.org/docs/hooks-effect.html#example-using-hooks-1
import React, { useEffect, useState } from 'react'
const Loading = () => {
const [loadingStatus, setLoadingStatus] = useState('.')
const [loop, setLoop] = useState()
useEffect(() => {
setLoop(setInterval(() => {
console.log("loading")
setLoadingStatus(loadingStatus + ".")
}, 1000))
return function cleanup() {
console.log('cleaning up')
clearInterval(loop)
}
}, [])
return (<p>
{`Loading ${loadingStatus}`}
</p>)
}
export default Loading
However , the loadingStatus variable only updates once and the setInterval loop doesnt get cleared even after the component stops mounting. Do I have to make this using a class component?
Clearing setInterval in React To stop an interval, you can use the clearInterval() method. ... useEffect(() => { const interval = setInterval(() => { setSeconds(seconds => seconds + 1); }, 1000); return () => clearInterval(interval); }, []); ...
To clear a timeout or an interval in React with hooks:Use the clearTimeout() or clearInterval() methods to remove the timeout when the component unmounts.
The hook comes with a cleanup function, which you might not always need, but it can come in handy. To invoke the cleanup function you can simply add a return function like so: useEffect(() => { // Your effect return () => { // Cleanup }; }, []); The cleanup can prevent memory leaks and remove unwanted things.
A pretty straightforward functional component that holds a state in counter . The state is incremented every second thanks to the setInterval defined in the useEffect .
Dependencies are our hint for React of when the effect should run, even though we set an interval and providing no dependencies []
, React wont know we want to run it more then once because nothing really changes in our empty dependencies []
.
To get the desired result we need to think when we want to run the effect ?
We want to run it when loadingStatus
changes, so we need to add loadingStatus
as our dependency because we want to run the effect every time loadingStatus
changes.
We have 2 options
Add loadingStatus
as our dependency.
const Loading = () => {
const [loadingStatus, setLoadingStatus] = useState(".");
const [loop, setLoop] = useState();
useEffect(
() => {
setLoop(
setInterval(() => {
console.log("loading");
setLoadingStatus(loadingStatus + ".");
}, 1000)
);
return function cleanup() {
console.log("cleaning up");
clearInterval(loop);
};
},
[loadingStatus]
);
return <p>{`Loading ${loadingStatus}`}</p>;
};
Make our effect not aware that we use loadingStatus
const Loading = () => {
const [loadingStatus, setLoadingStatus] = useState(".");
useEffect(() => {
const intervalId = setInterval(() => {
setLoadingStatus(ls => ls + ".");
}, 1000);
return () => clearInterval(intervalId);
}, []);
return <p>{`Loading ${loadingStatus}`}</p>;
};
Read more here => a-complete-guide-to-useeffect
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With