У меня есть компонент реакции, который отображает 2 элемента <video>.
В любое время виден только 1 элемент, и есть некоторая логика, которая обновляет состояние, поэтому эти переключатели.
У меня есть массив идентификаторов, и при каждом рендеринге переключателя состояния/игрока я хотел бы обновить воспроизводимое видео случайным видео.
(Ради этого вопроса я добавил кнопку для переключения состояния)
Если я выйду из своего состояния в методе рендеринга, я увижу, что реквизит url обновляется, как и ожидалось, однако видео не меняет источник.
Я выбираю переключение visibility элемента как display:none или что-то вроде
{playerOne.visible &&
<LandingPageVideoPlayer url = {playerOne.url} />
}
вызывает мигание при повторном отображении состояния.
Я не могу понять, как изменить источник видеоэлемента при повторном рендеринге.
Компоненты
const LandingPageVideoPlayer = ({ url, isActive }) => {
const playerClassName = `video-player ${isActive ? 'video-player--is-active' : null}`
return (
<video className = {playerClassName} autoPlay loop muted>
<source src = {url} type='video/mp4' />
</video>
)
}
class LandingPage extends Component {
MOCK_URL_SOURCE = [
'ehZqNokVylyWk',
'hDqq4LalRAUiQ',
'yjTccXlnh6LXW',
'3FjEPbKqEPhPpmC8uY',
'3ohs7NLUXtNW98mtIQ'
]
state = {
playerOne: {
visible: true,
url: `https://media0.giphy.com/media/3ohs7NLUXtNW98mtIQ/giphy.mp4`
},
playerTwo: {
visible: false,
url: `https://media0.giphy.com/media/3FjEPbKqEPhPpmC8uY/giphy.mp4`
}
}
randomItem = () => {
return this.MOCK_URL_SOURCE[Math.floor(Math.random() * this.MOCK_URL_SOURCE.length)]
}
toggle = () => {
this.setState(prevState => ({
playerOne: { visible: !prevState.playerOne.visible, url: `https://media0.giphy.com/media/${this.randomItem()}/giphy.mp4` },
playerTwo: { visible: !prevState.playerTwo.visible, url: `https://media0.giphy.com/media/${this.randomItem()}/giphy.mp4` }
}))
}
render() {
const { playerOne, playerTwo } = this.state
if (!playerOne || !playerTwo) {
return null
}
return (
<div className='landing-page'>
<button onClick = {this.toggle}></button>
<LandingPageVideoPlayer url = {playerOne.url} isActive = {playerOne.visible} />
<LandingPageVideoPlayer url = {playerTwo.url} isActive = {playerTwo.visible} />
</div>
)
}
}
export default LandingPage
Видеоплеер SCSS
.video-player {
position: absolute;
object-fit: cover;
width: 100%;
height: 100vh;
visibility: hidden;
&--is-active {
visibility: visible;
}
}



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


React не знает, какое видео нужно обновить, пока не будет предоставлено свойство key для каждого видео.
Поэтому, когда вы устанавливаете ключевую опору для видео на что-то уникальное, скажем, url передать игроку, это должно работать.
const LandingPageVideoPlayer = ({ url, isActive }) => {
const playerClassName = `video-player ${
isActive ? "video-player--is-active" : null
}`;
return (
..... ? .....
<video key = {url} className = {playerClassName} autoplay loop muted>
<source src = {url} type = "video/mp4" />
</video>
);
};
Посмотрите рабочую демонстрацию.
Для получения дополнительной информации о том, как работает свойство ключа, ознакомьтесь с официальной документацией Список и ключи.
Первое предложение гласит:
Keys help React identify which items have changed, are added, or are removed. Keys should be given to the elements inside the array to give the elements a stable identity
В вашем случае у вас есть два видео (которые на самом деле представляют собой список из двух элементов), поэтому, чтобы помочь React, какое видео изменилось, key поможет React определить, какое видео изменилось.
add key = {this.state.url} like this
<div className = "container">
<div className = "row">
<div className = "col-8">
<video width = "720" key = {this.state.url} height = "540" controls >
<source src = {this.state.url} type = "video/mp4" />
</video>
<h1>{this.state.url}</h1>
Отлично :) большое спасибо, что имеет смысл