campanto
campanto

Reputation: 17

SetTimeout in React last less than expected

I'm having trouble with my application's timer. In short, I have a timer that after 15 seconds changes the state of a component by setting "visibility: false". So far so good. The problem arises when I call the function before the 15 seconds have passed. The timer in that case does not last 15 seconds, in fact the component disappears after a few seconds. I think there is an interference problem between the "old" timer (probably still active) and the "new" timer. How can I do to avoid this? I would like the timer to be clean once I call another function (or even the same one) before starting the timeout. I hope I was clear. I attach the part of the code concerned for greater clarity.

import React, { Component } from "react";

class Pubblicita extends Component {
  state = {
    index: 0,
    iframeSrcs: ["/300x250", "/160x600", "/468x60"],
    heightSrcs: [250, 600, 60],
    widthSrcs: [300, 160, 468],
    visibility: false,
    leftSrcs: [1150, 50, 500],
    rightSrcs: [0, 0, 0],
    topSrcs: [10, 10, 500]
  };

  componentDidMount() {
    document.addEventListener("keydown", this.onKeyDown.bind(this));
  }

  componentWillUnmount() {
    document.removeEventListener("keydown", this.onKeyDown.bind(this));
  }

  onKeyDown(event) {
    if (event.keyCode === 17) {
      this.reload();
    }
    if (event.keyCode === 96) {
      this.setState({ index: 0, visibility: true });
    }
    if (event.keyCode === 97) {
      this.setState({ index: 1, visibility: true });
    }
    if (event.keyCode === 98) {
      this.setState({ index: 2, visibility: true });
    }
    this.timer();
  }

  timer() {
    setTimeout(() => {
      this.setState({ visibility: false });
    }, 15000);
  }

  reload() {
    const iframeLength = this.state.iframeSrcs.length;
    if (this.state.index < iframeLength) {
      this.setState({
        index: this.state.index + 1,
        visibility: true
      });
    } else {
      this.setState({ index: 0, visibility: true }); //starting again
    }
    this.timer();
  }

Upvotes: 0

Views: 273

Answers (2)

Umair Sarfraz
Umair Sarfraz

Reputation: 5953

Clear the old timer before triggering the new one.

timer() {
    if (this.timeout) {
        clearTimeout(this.timeout);
    }

    this.timeout = setTimeout(() => {
        this.setState({ visibility: false });
    }, 15000);
}

Upvotes: 2

Maksym Bezruchko
Maksym Bezruchko

Reputation: 1258

Yes, you are right. The problem is that you did not clear the previous timeout. Here is the example of how to solve such problem

Upvotes: 0

Related Questions