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>