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