Start a setTimeout in componentDidMount and end it in componentWillUnmount in React

812 views Asked by At

I'm here to ask for your help a little thing (I'm sure it's little) that is driving me crazy. First of all I'm pretty new to React and that's probably why it's hard for me to solve this issue. Basically I've put a slideshow on the site to show a picture every four seconds and it works perfectly, until I unmount the component that holds the slideshow (because the setTimeout didn't stop). I admit, at first I've decided to let it be, because it didn't kill the site, but then I discovered that it messes up with the mobile view so I have to fix it. The problem is: I cannot seem to be able to find a way to use clearTimeout in componentWillUnmount. Can you help me please? This is my component:

class PictureSlider extends React.Component {

componentDidMount() {
    
    var slideIndex = 0;
    showSlides();

    function showSlides() {
        var i;
        var slides = document.getElementsByClassName("mySlides");
        for (i = 0; i < slides.length; i++) {
            slides[i].style.display = "none";
        }
        slideIndex++;
        if (slideIndex > slides.length) { slideIndex = 1 }
        slides[slideIndex - 1].style.display = "block";
        setTimeout(showSlides, 4000)
        
    }
}

componentWillUnmount() {
}

render() {
    return (
        <div className="slideshow-container">
            <div className="mySlides fade">
                <img src="/images/photo/image00024.jpeg" style={{ width: '100%' }} />
            </div>

            <div className="mySlides fade">
                <img src="/images/photo/image00005.jpeg" style={{ width: '100%' }} />
            </div>

            <div className="mySlides fade">
                <img src="/images/photo/image00021.jpeg" style={{ width: '100%' }} />
            </div>

            <div className="mySlides fade">
                <img src="/images/photo/image00025.jpeg" style={{ width: '100%' }} />
            </div>

            <div className="mySlides fade">
                <img src="/images/photo/image00014.jpeg" style={{ width: '100%' }} />
            </div>

            <div className="mySlides fade">
                <img src="/images/photo/image00029.jpeg" style={{ width: '100%' }} />
            </div>

            <div className="mySlides fade">
                <img src="/images/photo/image00030.jpeg" style={{ width: '100%' }} />
            </div>

            <div className="mySlides fade">
                <img src="/images/photo/euro1ad.jpg" style={{ width: '100%' }} />
            </div>
        </div>
        );
}
2

There are 2 answers

1
akhtarvahid On BEST ANSWER

You can assign your setTimeout to a variable and clear that in componentWillUnmount.

Better way to handle image slider(Caurousel) using setInterval

Example

  componentDidMount() {
    var slideIndex = 0;

    this.timer = setInterval(() => {
      var i;
      var slides = document.getElementsByClassName("mySlides");
      for (i = 0; i < slides.length; i++) {
        slides[i].style.display = "none";
      }
      slideIndex++;
      if (slideIndex > slides.length) {
        slideIndex = 1;
      }
      slides[slideIndex - 1].style.display = "block";
    }, 4000);
  }

  componentWillUnmount() {
    clearInterval(this.timer);
  }

Live working demo

2
Prayag Choraria On

This is how you can do it.

class PictureSlider extends React.Component {
  state = {
    timeout: null,
  }

  componentDidMount() {
    var slideIndex = 0
    showSlides()

    function showSlides() {
      var i
      var slides = document.getElementsByClassName('mySlides')
      for (i = 0; i < slides.length; i++) {
        slides[i].style.display = 'none'
      }
      slideIndex++
      if (slideIndex > slides.length) {
        slideIndex = 1
      }
      slides[slideIndex - 1].style.display = 'block'
      // assign to state variable
      this.setState({ timeout: setTimeout(showSlides, 4000) })

    }
  }

  componentWillUnmount() {
    // clear the timeout assigned to state
    clearTimeout(this.state.timeout)
  }

  render() {
    return (
      <div className='slideshow-container'>
        <div className='mySlides fade'>
          <img src='/images/photo/image00024.jpeg' style={{ width: '100%' }} />
        </div>

        <div className='mySlides fade'>
          <img src='/images/photo/image00005.jpeg' style={{ width: '100%' }} />
        </div>

        <div className='mySlides fade'>
          <img src='/images/photo/image00021.jpeg' style={{ width: '100%' }} />
        </div>

        <div className='mySlides fade'>
          <img src='/images/photo/image00025.jpeg' style={{ width: '100%' }} />
        </div>

        <div className='mySlides fade'>
          <img src='/images/photo/image00014.jpeg' style={{ width: '100%' }} />
        </div>

        <div className='mySlides fade'>
          <img src='/images/photo/image00029.jpeg' style={{ width: '100%' }} />
        </div>

        <div className='mySlides fade'>
          <img src='/images/photo/image00030.jpeg' style={{ width: '100%' }} />
        </div>

        <div className='mySlides fade'>
          <img src='/images/photo/euro1ad.jpg' style={{ width: '100%' }} />
        </div>
      </div>
    )
  }
}