sap
sap

Reputation: 331

Conditional setInterval & clearInterval in ReactJS + Typescript

In single page web app, city's map rendered with traffic layer.
Currently, working on a live mode switch, which if ON should update the traffic layer on map every 5 minutes.
When live mode is switched off, the 5 minute timer should go off.

For this requirement, got hints for two options from few blogs & posts.
1. Javascript methods: setInterval and clearInterval
2. Use of web sockets

Since this web app has only couple of users besides lack of knowledge for web sockets, decided to go with the first option. However, faced difficulty in successful execution of clearInterval() when switch goes to off mode.
In the code below, 'timeout' value passed to clearInterval is always undefined.

const handleOkBtnClick = (): void => {
    let timeout;
    if(live){
          timeout = setInterval(updateFilter, 60000);
          console.log('live ON == '+ timeout); // prints number like 89 or 146
        }else{
          console.log('live Off == '+ timeout); //always prints 'undefined' 
          clearInterval(timeout);           
        }
    }
}

It looks like conditional execution of setInterval and clearInterval isn't an option.
Jumping in to javascript development after a decade, What am I missing?
Any suggestion for alternative approach will be appriciated.
Using ReactJS v16.11, Typescript v3.7

Upvotes: 0

Views: 2752

Answers (2)

Shubham Khatri
Shubham Khatri

Reputation: 281874

The issue here is that timeout variable is defined within handleOkBtnClick so whenever this function is called, the timeout value is reset to undefined and if live is true, its set to timerId

The solution here is to move the timer to a class variable

class TrafficLights extends React.Component {
   timeout = null
   ...
   handleOkBtnClick = (): void => {
    if(live){
          this.timeout = setInterval(updateFilter, 60000);
          console.log('live ON == '+ this.timeout); // prints number like 89 or 146
        }else{
          console.log('live Off == '+ this.timeout); 
          clearInterval(this.timeout);           
        }
     }
   }
   ...
}

Now it looks like you use functional component, so you can store the timeout in a useRef if you use react-hooks

const TrafficLights = () =>   {
   const timeout = useRef<number | null>(null);
    ...
     const handleOkBtnClick = (): void => {
        if(live){
              timeout.current = window.setInterval(updateFilter, 60000);
              console.log('live ON == '+ timeout.current); // prints number like 89 or 146
            }else{
              console.log('live Off == '+ timeout.current); 
              clearInterval(timeout.current);           
            }
         }
       }
      ...
  }

Upvotes: 2

sap
sap

Reputation: 331

const [timeout, setTimeout] = useState(0);  
const handleOkBtnClick = (): void => {

    if(live){      
      setTimeout(window.setInterval(updateFilter, 60000));
      console.log('timeout == '+ timeout);
    }else{
      console.log('clearInterval == '+ timeout); 
      clearInterval(timeout);          
    }
} 

This code is working without any warning or error.
But, pros and cons of using window.setInterval Vs. setInterval if any, should be taken into consideration.

Upvotes: 0

Related Questions