ReactJS can't change video and poster videojs

This is a problem with destructive libraries. Basically what happens is you render the <video> element, and then VideoJS injects a bunch of sibling elements next to your <video> (child elements are fine).

React tries to update the element, and it can't figure out what's going on, so it panics and gives that error.

So you have two options:

Option 1: render a <div ref="target" />, construct the video node in componentDidMount and this.refs.target.appendChild(that), and then invoke VideoJS manually. In componentWillRecieveProps you need to update the poster img's src directly.

Option 2: fork video.js and make it only emit events instead of directly modifying the DOM. Your component would react to those events, modifying state, and rendering the poster, buttons, etc.

Option 1 is easier, option 2 is potentially more efficient and cleaner. I'd go with option 1.


Neither of these are good solutions, but libraries that escape their container don't play nicely with react.


In case someone needs an example of the answer from FakeRainBrigand, here's how my video class looks in the end.

Video = React.createClass({
  componentDidMount: function() {
    var video, wrapper;
    wrapper = document.createElement('div');
    wrapper.innerHTML = "<video id='attachmentVideo' class='video-js vjs-default-skin' controls preload='auto' width='640' height='264' poster='" + this.props.thumbnail + "'><source src='" + this.props.url + "' type='video/mp4' /><p className='vjs-no-js'>To view this video please enable JavaScript, and consider upgrading to a web browser that <a href='http://videojs.com/html5-video-support/' target='_blank'>supports HTML5 video</a></p></video>";
    video = wrapper.firstChild;
    this.refs.target.getDOMNode().appendChild(video);
    return videojs(video, {});
  },
  render: function() {
    return (
      <div id="attachmentViewer">
        <h2>{this.props.title}</h2>
        <div id="attachmentVideoContainer" ref="target" />
      </div>
    );
  }
});