ReactJS cannot change video and poster videojs

I want to change the video poster and the source of the VideoJS when selected

var VideoPlayer = React.createClass({ render: function() { var selectedVideo = this.props.selectedVideo; function filterVideo(video) { return video.id == selectedVideo; } var data = this.props.videos.filter(filterVideo); return ( <div className="col-md-6 videoplayer"> <h2>{data[0].title}</h2> <video id="videoplayer" className="video-js vjs-default-skin vjs-big-play-centered" controls preload="none" width="100%" height="300" poster={data[0].poster} data-setup="{}"> <source src={data[0].video} type='video/mp4' /> </video> <div className="video-description"> {data[0].description} </div> </div> ); } }); 

but I got an error:

 Uncaught Error: Invariant Violation: ReactMount: Two valid but unequal nodes with the same `data-reactid`: .0.0.1.1 

title and description changed, but video poster does not change

+7
reactjs
source share
4 answers

This is a problem with destructive libraries. Basically, you render the <video> element, and then VideoJS introduces a few sibling elements next to your <video> (child elements are ok).

React is trying to update the element, and it cannot understand what is happening, so it panics and gives this error.

So, you have two options:

Option 1: render <div ref="target" /> , build a video node in the this.refs.target.appendChild(that) component and this.refs.target.appendChild(that) , and then call VideoJS manually. In the WillRecieveProps component, you need to update the img src poster directly.

Option 2: fork video.js and do this only to generate events instead of directly modifying the DOM. Your component will respond to these events, change the state and rendering of the poster, buttons, etc.

Option 1 is simpler; option 2 is potentially more efficient and clean. I would choose option 1.


None of them is a good solution, but libraries that exit their container do not respond very well to the reaction.

+16
source share

If someone needs an example response from FakeRainBrigand, here is what my video class looks like at 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> ); } }); 
+11
source share

Not 100% related, but if you are looking for a cleaner solution for implementing videoJS as a component, this is what I did ...

The last post was some time ago, and I don't know if anyone came up with a better implementation, however I did the following:

  • A videojs function has been added as an attribute of getInitialState, and support for "videoHTML" for getInitialState has been added.
  • Generated my video tag and sources in the componentDidMount method and assigned this variable string to maintain the state of the HTML video.
  • Added object () of created instance of vjs player and replaceState initial state to componentWillUnmount () method.
  • The __initVideo (elem) component function has been added, which checks whether the transmitted element has child elements, and if it does this "this.vjsPlayer = this.state.initVideoJS (elem.children [0], {})". Then I return this.vjsPlayer.
  • In the div application in the render () method, I set the prop dangerous SetInnerHTML to prop. this.state.videoHTML and set ref, which calls the __initVideo function, passing in the div.

It is not possible to post any code, but it is as close as possible to the pure React VideoJS implementation that I was able to figure out.

0
source share

1. Import ReactDOM imports from Reaction-DOM

2.inside function this.setstate ({vidio: "{new url as source}") var name = ReactDOM.findDOMNode (this.video) name.src = this.state.video.url

3.Template

this.video = video} src = {this.state.video.url}

  /> 
0
source share

All Articles