我该如何告诉React中的一个子元素寻求其视频元素?

时间:2019-02-28 22:53:09

标签: reactjs imperative-programming declarative-programming

我有一个带有视频播放器的简单React应用,并显示了有关视频的数据的图表。两者都位于顶层的各自组件中:

class App extends Component {
  ...
  render() {
    return (
      <div className="App">
        <VideoDisplay .../>
        <MetricsDisplay .../>
      </div>
    )
  }
}

内部VideoDisplay.js是一个我想控制的<video>元素,特别是通过寻找其播放位置,我可以使用videoElement.currentTime=seekToTime进行控制。我想通过MetricsDisplay元素进行控制:如果我点击图表,则希望视频搜索到点击的时间。但是,这样做似乎必须从VideoDisplay.js调用App.js的{​​{1}}中的函数。但这是命令性的,而不是声明性的,确实我在React中实现它遇到了麻烦。可能吗在同级元素的点击触发后,我还能如何告诉该元素中的视频进行搜索?

我有一个解决方法,我将作为答复发布,但我非常确信从设计角度来看这是次优的,并且会引起代码维护的麻烦。那么有什么更好的方法呢?做这样的事情的“反应”方式是什么?

请参阅所附的屏幕截图:单击右侧的图形时,视频应搜索到单击的时间点。

Video and metrics screenshot

1 个答案:

答案 0 :(得分:0)

因此,为了解决这个问题,我可以在道具中传递寻道时间,并防止它反复寻道,我可以增加一个seekId计数器。这似乎很倒退,这是因为我正在使用旨在避免这种情况的声明性逻辑来重新创建命令性逻辑,还因为我指示视频元素具有我要视频寻求的位置的持久“属性”到现在以及执行此操作的命令的ID。

也就是说,我使用MetricsDisplay中的此功能响应来自App.js元素的点击:

class App extends Component {
  ...
  setPlayheadTime(time) {
    this.setState((state, props) => ({seekTo: time, seekId: state.seekId + 1}));
  }
  ...
}

我将seekToseekId都传递给VideoDisplay并在MetricsDisplay.js的生命周期函数中处理它:

class VideoDisplay extends Component {
  ...
  componentWillUpdate() {
    if (this.props.seekTo && this.props.seekId !== this.seekId) { this.seekTo(this.props.seekTo); }
  }

  seekTo(time) {
    console.log(`(${this.props.seekId}) Seek to ${time}`);
    this.seekId = this.props.seekId;
    document.getElementById("the-video").currentTime = time;
  }
  ...
}

这可行,但是我必须相信这不是完成“普通” javascript中简单回调函数的最佳方法。有什么建议么?我想念什么?