Search code examples
javascriptreactjstimeoutslideshow

Set TimeOut to React Function


I have the following object list:

mediaList[
 {id:1, url:"www.example.com/image1", adType:"image/jpeg"},
 {id:2, url:"www.example.com/image2", adType:"image/jpg"},
 {id:3, url:"www.example.com/video1", adType: "video/mp4"}
]

I need to create a slideshow that has a configurable duration (1s, 5, 10s). So far I can generate a list of the media from the mediaList

  renderSlideshow(ad){
    let adType =ad.adType;
    if(type.includes("image")){
      return(
        <div className="imagePreview">
          <img src={ad.url} />
        </div>
      );
    }else if (adType.includes("video")){
      return(
        <video className="videoPreview" controls>
            <source src={ad.url} type={adType}/>
          Your browser does not support the video tag.
        </video>
      )

    }
  }

 render(){   
    return(
      <div>
          {this.props.mediaList.map(this.renderSlideshow.bind(this))}
      </div>
    )
 }

What I want to do now is generate the media one at a time with configurable durations for autoplay.

I know I need to use some form of a setTimeout function like this example:

setTimeout(function(){
         this.setState({submitted:false});
    }.bind(this),5000);  // wait 5 seconds, then reset to false

I'm just not sure how to implement it for this scenario. (I believe I'll need to use css for the fade transitions but I'm just stumped on how to create the transition in the first place)


Solution

  • If you want to change the media on every 5 seconds, you will have to update the state to re-render your components You can also use setInterval instead of setTimeout. setTimeout will be triggered only once, setInterval will be triggered every X milliseconds. Here what it may look like:

    class MyComponent extends React.Component {
      constructor(props) {
        super(props);
        this.state = { activeMediaIndex: 0 };
      }
    
      componentDidMount() {
        setInterval(this.changeActiveMedia.bind(this), 5000);
      }
    
      changeActiveMedia() {
        const mediaListLength = this.props.medias.length;
        let nextMediaIndex = this.state.activeMediaIndex + 1;
    
        if(nextMediaIndex >= mediaListLength) {
          nextMediaIndex = 0;
        }
    
        this.setState({ activeMediaIndex:nextMediaIndex });
      }
    
      renderSlideshow(){
        const ad = this.props.medias[this.state.activeMediaIndex];
        let adType = ad.adType;
        if(type.includes("image")){
          return(
            <div className="imagePreview">
              <img src={ad.url} />
            </div>
          );
        }else if (adType.includes("video")){
          return(
            <video className="videoPreview" controls>
                <source src={ad.url} type={adType}/>
              Your browser does not support the video tag.
            </video>
          )
    
        }
      }
    
      render(){   
        return(
          <div>
              {this.renderSlideshow()}
          </div>
        )
      }
    }
    

    Basically what the code is doing is that every 5 seconds, will change the activeMediaIndex to the next one. By updating the state, you will trigger a re-render. When rendering the media, just render one media (you can also render the previous one and the next one like a classic slideshow). Thus way, every 5 seconds, you will render a new media.