React.js + video element: set current play time from props?

I just got started reacting and this is a problem I haven't seen a good solution for yet. The problem is that I want to set the video to play in the tag in place when the user clicks the button.

My current solution is the following:

componentDidUpdate(prevProps, prevState) {
    console.log("Updating to timestamp: " + this.props.timestamp);
    var timestamp = this.props.timestamp;
    if (timestamp != prevProps.timestamp) {
        React.findDOMNode(this.refs.theVideo).currentTime = timestamp;
    }
}

      

The problem is it seems really hacky. Now I'm in a situation where the user can double-click the same button and nothing happens, so I'm looking at adding more state to the component to make sure this case works correctly.

Is this the correct approach? Anything that reacts so far seems super logical, but it just isn't quite right. Would this be the situation where you expose a method to a parent method?

+3


source to share


1 answer


You touched on one solution in your question - you can expose a method on the child that sets the timestamp. However, this is a very important API and may not fit well in an otherwise declarative application.

In a recent project, I implemented something like this with a declarative API using acomponentWillReceiveProps

very similar solution to your own solution:

componentWillReceiveProps: function(props) {
  if (this.props.playing !== props.playing) {
    this.audio[props.playing ? "play" : "pause"]();
  }

  if (this.props.lastSeek !== props.lastSeek) {
    var start = props.start,
        offset = props.currentTime - start;
    this.audio.currentTime = offset / 1000;
  }
}

      

By comparing the property given to the component the last time it was rendered with the data given to it this time, we can determine that the audio clip timing needs to be adjusted.



I think the best solution is to create a custom component <Video>

with the sole purpose of hiding such an imperative API behind a declarative API; then your application doesn't need to know about the imperative API. So, in your application, you can use

render() {
  // ...
  <Video url={...} timestamp={this.props.timestamp} />
}

      

You can learn more about this concept in this meeting: "Overcoming imperative APIs with Kinetophone" (around 7:04).

+3


source







All Articles