title: React.js components synchronization with html5 media current time
body: <p>I have a React.js component, which is an <code>audio</code> file and a child component, where is a slider with play/pause button. I want arrow position in slider synchronized with audio current time.</p>
  
  <p>When audio is playing, arrow animation is delayed, sometimes more and sometimes less. When audio is paused arrow animation occurs immediately. How can I achieve the same effect when audio is playing without delay?</p>
  
  <p><a href="https://jsfiddle.net/69z2wepo/86820/" rel="nofollow noreferrer">jsfiddle</a></p>
  
  <pre><code>  class Player extends React.Component {
  
    constructor(props) {
      super(props);
  
      this.state = {
      };
  
      this.playClick = this.playClick.bind(this);
      this.changePosition = this.changePosition.bind(this);
    }
  
    componentWillReceiveProps(nextProps) {
      const that = this;
      if (this.props.currentTime !== nextProps.currentTime) {
          const horizontalOffset = nextProps.currentTime * 500 / this.props.duration;
        console.log('horOffset', horizontalOffset);
        $('.arrow').animate(
          { left: `${horizontalOffset - 20}px` },
          {
            duration: 'slow',
            easing: 'easeInOutExpo',
          },
        );
      }
    }
  
    changePosition(e){
      const newCurrTime = this.props.duration * e.clientX / 500;
      console.log('changed time', newCurrTime);
      this.props.onChangeAudioTime(newCurrTime);
    }
  
    playClick() {
      this.props.onTogglePlay();
    }
  
    render() {
      return &lt;div&gt;
      &lt;button onClick={this.playClick}&gt;play&lt;/button&gt;
      &lt;div className="slider-content" onClick={this.changePosition}&gt;
        &lt;div className="arrow"&gt;
        &lt;/div&gt;
      &lt;/div&gt;
      &lt;/div&gt;;
    }
  }
  
  class Audio extends React.Component {
  
    constructor(props) {
      super(props);
  
      this.state = {
        play: false,
        current: 0,
        duration: 2024.496,
        seeked: false
      };
  
      this.toggle = this.toggle.bind(this);
      this.play = this.play.bind(this);
      this.pause = this.pause.bind(this);
      this.setCurrTime = this.setCurrTime.bind(this);
    }
  
    componentDidMount() {
      const that = this;
      this.currentTimeInterval = null;
  
      this.audio.onplay = () =&gt; {
        this.currentTimeInterval = setInterval(() =&gt; {
          if (that.state.current !== this.audio.currentTime) {
            that.setState({ current: this.audio.currentTime, seeked: false });
          }
        }, 500);
      };
  
      this.audio.onseeked = () =&gt; {
        this.currentTimeInterval = setInterval(() =&gt; {
          if (that.state.current !== this.audio.currentTime) {
            that.setState({ current: this.audio.currentTime, seeked: false });
          }
        }, 500);
      };
  
      this.audio.onpause = () =&gt; {
        clearInterval(this.currentTimeInterval);
      };
    }
  
    play() {
      this.setState({ play: true }, () =&gt; {
        this.audio.play();
      });
    }
  
    pause() {
      this.setState({ play: false }, () =&gt; {
        this.audio.pause();
      });
    }
  
    toggle() {
      this.state.play ? this.pause() : this.play();
    }
  
    setCurrTime(newCurrTime) {
      let that = this;
      clearInterval(this.currentTimeInterval);
      this.setState({ current: newCurrTime, seeked: true }, () =&gt; {
        this.audio.currentTime = newCurrTime;
      });
    }
  
    render() {
      return &lt;div&gt;
      &lt;audio src="https://dts.podtrac.com/redirect.mp3/www.kqed.org/.stream/mp3splice/radio/theleap/2017/04/HennyMastered.mp3"
            id="audio"
            ref={el =&gt; (this.audio = el)}
          /&gt;
       &lt;Player
              currentTime={this.state.current}
              duration={this.state.duration}
              onTogglePlay={this.toggle}
              onChangeAudioTime={this.setCurrTime}
              play={this.state.play}
              ref={el =&gt; (this.player = el)}
            /&gt;
      &lt;/div&gt;;
    }
  }
  
  ReactDOM.render(
    &lt;Audio name="World" /&gt;,
    document.getElementById('container')
  );
  </code></pre>