Как мне сказать, чтобы дочерний элемент в React искал его элемент видео?

У меня есть простое приложение React с видеоплеером и диаграммой, отображающей данные о видео. Оба находятся в своих собственных компонентах на верхнем уровне:

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

внутри VideoDisplay.js это <video> элемент, который я хочу контролировать, в частности, путем поиска его игровой позиции, что я могу сделать с помощью videoElement.currentTime=seekToTime, Я хочу контролировать это с MetricsDisplay элемент: если я нажимаю на график, я хочу, чтобы видео искало время, на которое нажали. Но для этого, кажется, мне нужно вызвать функцию в VideoDisplay.js от App.js когда он получает щелчок от MetricsDisplay.js, Но это обязательно, а не декларативно, и у меня действительно возникают проблемы с реализацией этого в React. Это вообще возможно? Как еще я могу указать видео в элементе для поиска, вызванное щелчком по элементу-родителю?

У меня есть обходной путь, который я опубликую в качестве ответа, но я очень убежден, что он довольно неоптимален с точки зрения дизайна и вызовет проблемы с обслуживанием кода. Так какой метод лучше? Что такое "Реагировать", чтобы сделать что-то подобное?

Смотрите прикрепленный скриншот: при нажатии на график справа видео должно стремиться к нажатому моменту времени.

1 ответ

Таким образом, чтобы обойти это, я могу провести время поиска в подпорках, и чтобы предотвратить его повторный поиск, я могу увеличить seekId счетчик. Это выглядит очень задом наперед, потому что я воссоздаю императивную логику, используя очень декларативную логику, предназначенную для того, чтобы этого избежать, и потому что я указываю, что элемент видео имеет постоянное "свойство" позиции, которую я хочу, чтобы видео искало на данный момент и идентификатор команды, чтобы сделать это.

То есть я отвечаю на клик с MetricsDisplay элемент с этой функцией в App.js:

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

Я прохожу оба seekTo а также seekId в 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 является простой функцией обратного вызова. Какие-либо предложения? Что мне не хватает?

Другие вопросы по тегам