HTML 视频标签不会在重新渲染时更新源代码

Tim*_*m J 3 javascript html5-video reactjs

我有一个渲染 2 个<video>元素的 react 组件。

在任何时候只有 1 个元素是可见的,并且有一些更新状态的逻辑,所以这些切换。

我有一个 id 数组,在每次渲染状态/播放器切换时,我想用随机视频更新正在播放的视频。

(为了这个问题,我添加了一个按钮来切换状态)

如果我在渲染方法中注销我的状态,我可以看到url道具按预期更新,但是视频不会更改源。

我选择visibility将元素的切换为display:none或类似的

{playerOne.visible &&
    <LandingPageVideoPlayer url={playerOne.url} />
}
Run Code Online (Sandbox Code Playgroud)

重新渲染状态时会导致闪烁。

我不知道如何在重新渲染时更改视频元素的来源。

成分

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
Run Code Online (Sandbox Code Playgroud)

视频播放器 SCSS

  .video-player {
    position: absolute;
    object-fit: cover;
    width: 100%;
    height: 100vh;
    visibility: hidden;

    &--is-active {
      visibility: visible;
    }
  }
Run Code Online (Sandbox Code Playgroud)

dan*_*die 10

除非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>
  );
};
Run Code Online (Sandbox Code Playgroud)

查看工作演示。
编辑 so.answer.57235013

有关 key 属性如何工作的更多信息,请查看官方文档List 和 Keys

第一句话是这样写的

键帮助 React 识别哪些项目已更改、添加或删除。应为数组内的元素提供键,以使元素具有稳定的身份

在您的情况下,您有两个视频(实际上是两个项目的列表),因此为了帮助 React 哪个视频发生了变化,key将有助于 React 识别哪个视频发生了变化。