I have this component:
function App() {
const deployIntervalRef = React.useRef(null);
React.useEffect(() => {
deployIntervalRef.current = setInterval(() => {
console.log("interval handler");
console.log(deployIntervalRef.current);
clearInterval(deployIntervalRef.current);
deployIntervalRef.current = null;
},2000);
}, []);
return <div></div>;
}
ReactDOM.createRoot(document.getElementById('root')).render(<React.StrictMode><App/></React.StrictMode>);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.development.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.development.min.js"></script>
<div id="root"/>
In my mind, it should output “interval handler” once and then stop,but it doesn’t. Why?
From the second log, you can see that when clear, ref has an interval id
>Solution :
StrictMode is causing your component to be double mounted, which in turn is causing a second interval to be created.
The problem is the ref is being reassigned to null before the second interval can be cleared. So your second interval runs infinitely.
Demo of problem
function App() {
console.log('mounted')
const deployIntervalRef = React.useRef(null);
React.useEffect(() => {
deployIntervalRef.current = setInterval(() => {
console.log("interval handler");
console.log(deployIntervalRef.current);
clearInterval(deployIntervalRef.current);
deployIntervalRef.current = null;
},2000);
console.log(deployIntervalRef.current);
}, []);
return <div></div>;
}
ReactDOM.createRoot(document.getElementById('root')).render(<React.StrictMode><App/></React.StrictMode>);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.development.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.development.min.js"></script>
<div id="root"/>
Demo without StrictMode
function App() {
console.log('mounted')
const deployIntervalRef = React.useRef(null);
React.useEffect(() => {
deployIntervalRef.current = setInterval(() => {
console.log("interval handler");
console.log(deployIntervalRef.current);
clearInterval(deployIntervalRef.current);
deployIntervalRef.current = null;
},2000);
console.log(deployIntervalRef.current);
}, []);
return <div></div>;
}
ReactDOM.createRoot(document.getElementById('root')).render(<App/>);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.development.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.development.min.js"></script>
<div id="root"/>