HTML 视频标签在重新渲染时未更新源
HTML Video tag not updating source on re render
我有一个呈现 2 个 <video>
元素的反应组件。
任何时候只有 1 个元素可见,并且有一些逻辑可以更新状态,因此这些切换。
我有一个 ID 数组,在 state/player 切换的每个渲染中,我想用随机视频更新正在播放的视频。
(为了这个问题,我添加了一个切换状态的按钮)
如果我在渲染方法中注销我的状态,我可以看到 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;
}
}
除非为每个视频提供 key
属性,否则 React 不知道要更新哪个视频。
因此,当您将视频的关键道具设置为独特的东西时,比如 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>
);
};
有关密钥 属性 工作原理的更多信息,请查看官方文档 List and Keys。
第一句写着,
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>
我有一个呈现 2 个 <video>
元素的反应组件。
任何时候只有 1 个元素可见,并且有一些逻辑可以更新状态,因此这些切换。
我有一个 ID 数组,在 state/player 切换的每个渲染中,我想用随机视频更新正在播放的视频。
(为了这个问题,我添加了一个切换状态的按钮)
如果我在渲染方法中注销我的状态,我可以看到 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;
}
}
除非为每个视频提供 key
属性,否则 React 不知道要更新哪个视频。
因此,当您将视频的关键道具设置为独特的东西时,比如 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>
);
};
有关密钥 属性 工作原理的更多信息,请查看官方文档 List and Keys。
第一句写着,
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>