12

On each question component, I am trying to clear the time out. So on componentWillMount() I will start the timer and then on componentDidUpdate() I will clear the timeout. The timer does not seem to be working.After the timer expires I will push the user back to the home page. Any idea why the using clearTimeout() isnt working?

class Questions extends Component { 
    constructor(props){
        super(props);
        this.state ={
            error: false,
            position: null,
            redirect: false
        } 
        this.error = this.error.bind(this);   
        this.errorFalse = this.errorFalse.bind(this); 
        this.timer = this.timer.bind(this); 
    }
    timer=()=>{
        setTimeout(() => { 
            console.log('this ran') 
            this.setState({
                redirect: true
            })

    }, 5000)
    }
    componentWillMount(){
        this.setState({
            error: false
        })
        this.timer();

    }
    componentDidUpdate(prevProps, prevState, snapshot, timer){
        console.log('updated')
        clearTimeout(this.timer);
    }
jdip88
  • 427
  • 2
  • 9
  • 23
  • Possible duplicate of [setTimeout / clearTimeout problems](https://stackoverflow.com/questions/3015319/settimeout-cleartimeout-problems) – Herohtar Apr 11 '18 at 20:29

3 Answers3

22

React Hooks

useEffect(() => {
    const timer = setTimeout(() => ...some work ... , 2000);

    return () => {
      clearTimeout(timer);
    };
  });
Nik Sumeiko
  • 8,263
  • 8
  • 50
  • 53
Milan Vukovic
  • 221
  • 2
  • 3
  • `useEffect` hooks run the code only one time. @NorbertBiró – Salman Jul 04 '22 at 20:52
  • Answer was edited 2 days ago with the comment "Drops unnecessary abstraction", so my comment seem to be out of context now. But. My comment had nothing to do with `useEffect`, and you are also incorrect here because `useEffect` runs on every render in this example, since an empty array was not passed as a second argument. @Salman – Norbert Biró Jul 07 '22 at 09:05
18

When you use setTimeout() it returns a timeoutID, which you use to clear the timeout.

To use it in your component, you need to store the timeoutID that was returned from the timer method:

class Questions extends Component {
  constructor(props) {
    super(props)
    this.state = {
      error: false,
      position: null,
      redirect: false
    }
    this.error = this.error.bind(this);
    this.errorFalse = this.errorFalse.bind(this);
    // this.timer = this.timer.bind(this); // don't bind an arrow function
  }
  timer = () => setTimeout(() => { // return the timeoutID
    console.log('this ran')
    this.setState({
      redirect: true
    })

  }, 5000);
  componentWillMount() {
    this.setState({
      error: false
    })
    this.timeoutID = this.timer(); // cache the timeoutID
  }
  componentDidUpdate(prevProps, prevState, snapshot, timer) {
    console.log('updated')
    clearTimeout(this.timeoutID); // clear the timeoutID
  }
Ori Drori
  • 183,571
  • 29
  • 224
  • 209
8

The best way in React to clear Timeouts and Intervals are by assinging ref to your interval/timeout functions which works flawlessly and use useRef() hook

clearTimerRef = useRef();
clearIntervalRef = useRef();

clearTimerRef.current = setTimeout(timerFunction, 5000);
clearIntervalRef.current = setInterval(intervalFunction, 5000); 

const stopFunction = () => {
     clearInterval(clearIntervalRef.current)
     clearTimeout(clearTimerRef.current)
} 
Aarush Sharma
  • 99
  • 2
  • 2