-
Notifications
You must be signed in to change notification settings - Fork 7.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How to integrate properly videojs with reactjs? #3816
Comments
This is something we are planning to write a guide for. There has been a fair amount of discussion on this topic, though. There was some discussion of using React with video.js in #2006 (particularly, check out @chemoish's comment). And there are a few packages on npm offering React components with video.js integration; however, they don't look very popular. That said, video.js operates on DOM elements; so, it's definitely possible. I'm not a React expert, but it looks like you'll want to use I believe there was also a caveat with getting React to ignore the player's DOM as well. |
Thanks for the reply. I wish that we get the guide pretty soon since this is the best JS player that we could find and we are really excited to see it in Action (in React website). |
You're welcome! I wouldn't wait on the guide, though. We have a lot of work that is currently in progress and we likely won't get to new guides until after the new year. |
@codeismine The code I posted is very old, as things change every week, but the concepts are the same.
However, there is nothing special to do that to use normal render() {
return (
<video ref={(c) => this.player = c } />
);
} Reference/execute (This is just one approach, you can do it differently, hopefully concepts are understandable) |
@chemoish: I have followed your's comment on #2006 class ReviewDetailVideo extends Component {
} |
@codeismine Not sure what the problem is? What is not working? What is PFB code? The comment I made above should indicate that my post was old and that the code is out of date, but maybe that wasn't clear? If you notice, I posted a code block in the previous comment which would indicate that the implementation can/has changed (maybe the es6 syntax is confusing?). render() {
return (
<video ref={(c) => this.player = c } />
);
} It looks like there might be fundamental knowledge gaps in the usage of |
@chemoish Never mind. I guess I was asking help from the wrong person! Thanks for providing information anyways. |
Sorry,,, I can't help. I would recommend not managing the DOM elements yourself because I might recommend trying this out (looks like with your code it is already es6'ish)… If it is not on the right path, feel free to ignore—it actually may be a /* global videojs */
componentDidMount() {
this.player = videojs(this.videoPlayer, {
src: 'http://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_320x180.mp4',
}, () => {
// on ready function for anything else you need to do
// after the player is set up…
});
}
componentWillUnmount() {
this.player.dispose();
// whatever other things you need to clean up—maybe remove the DOM reference
this.videoPlayer = undefined;
}
render() {
return (
<video
id="videoPlayer"
ref={(c) => { this.videoPlayer = c; }}
/>
);
} Hope this helps or gives some insight. |
This is how we use it in React import React, {Component} from 'react'
export default class VideoPlayer extends Component {
static propTypes = {
video: PropTypes.object.isRequired,
}
state = {}
componentDidMount() {
const {videojs} = global
if (!videojs) {
return
}
const {video} = this.props
this.state.player = videojs(video.id)
}
componentWillUnmount() {
if (this.state.player) {
this.state.player.dispose()
}
}
render() {
const {video: {id, src, poster}} = this.props
const videoHtml = `
<video id="${id}" class="video-js vjs-default-skin" controls
preload="auto" poster="${poster}"
>
<source src="${src}" type="video/mp4" />
<p class="vjs-no-js">
To view this video please enable JavaScript
</p>
</video>
`
return (
<div dangerouslySetInnerHTML={{__html: videoHtml}}></div>
)
}
} |
Thanks for sharing @haio! |
Also, I just wanted to add that as part of 5.15 we added a new feature to allow ingesting a div wrapper as the player element rather than using creating a new one: #3856. All that's required is adding a |
So far no one has commented that styles must also be loaded properly I am using
This assumes Webpack is being used, so the loaders are explicit to prevent CSS Modules wrapping everything into a namespace. This way one can make sure that React is using the same version of JS and CSS from video.js |
A guide for using React & video.js is currently in being reviewed. Hopefully that will help everyone that is currently having an issue working with React and video.js |
@brandonocasey - Affirmative its working. Thanks for a great job! Something like this: |
@codeismine Here should be an example of this working—hopefully it meets your use case. |
I've tried the recommendation given in your guides about how to integrate this with React. I was able to track the issue down to this line in the "Player.prototype.createEl" function: Object.getOwnPropertyNames(attrs).forEach(function (attr) {
// workaround so we don't totally break IE7
// http://stackoverflow.com/questions/3653444/css-styles-not-applied-on-dynamic-elements-in-internet-explorer-7
if (attr === 'class') {
el.className += ' ' + attrs[attr];
} else {
el.setAttribute(attr, attrs[attr]);
}
}); This basically copies all the attributes of the video element onto the parent div element right ? And unfortunately the 'data-reactid' attribute also gets copied and hence you now have two DOM elements with the same id, and that's where React starts screaming. I could make a pull request with a quick fix of ignoring the data-reactid attribute when adding it on the parent div element. What would you guys suggest ? |
@MohammedSiddiqui10p maybe things aren't getting mounted and unmounted correctly? It is been a very long time since I have used |
Thank you @chemoish, this should do the trick (Y) |
Any tips on updating the component through From my attempts, I got the following problems:
|
Phew, I finally got it working. I'm recreating the video instance and disposing old ones by managing an Here's an untested sample of the main idea (my actual component has a lot of unrelated stuff): export default class VideoPlayer extends Component {
constructor(props) {
super(props);
this.state = {
updateCount: 0
};
}
setup() {
let updateCount = this.state.updateCount;
this.setState({
updateCount: updateCount + 1
});
}
componentDidMount() {
this.setup();
}
componentWillReceiveProps(nextProps) {
// You should probably change this check
if(this.props !== nextProps)
this.setup();
}
componentDidUpdate(prevProps, prevState) {
if(this.state.updateCount !== prevState.updateCount) {
// If it has a player, dispose
if(this.player) {
this.player.dispose();
}
// Create new player
this.player = videojs(this.videoNode, this.props);
}
}
componentWillUnmount() {
// Dispose player on unmount
if(this.player) {
this.player.dispose();
}
}
render() {
// Use `key` so React knows this item is going to change
const key = `${this.props.id || ''}-${this.state.updateCount}`;
return (
<div key={key} data-vjs-player>
<video ref={ node => this.videoNode = node } className="video-js"></video>
</div>
)
}
} |
We have a simple starting guide now. http://docs.videojs.com/tutorial-react.html |
Hi, I have successfully implemented the basic example of creating a child vjs component within a parent component that initializes fine when I pass a videoJSOptions const via a spread operator like so: <VideoPlayer {...videoJsOptions} /> where videoJSOptions is defined as a const in the parent component: const videoJsOptions = { What I am trying to do now is to dynamically update the sources array by instead changing the initial videoJsOptions to remove the sources array completely, and then create a state object in the parent called sources which initializes as an empty array. So the parent state looks like this: state = { ...and the VJS component now looks like this: <VideoPlayer {...videoJsOptions} sources={this.state.sources} /> Then there is a play list of various elements in the parent that I've created an onClick that is handled by the parent like so: handler(videoUrl){ This approach does not seem to update the player at all. When I do a console log within the VJS component's componentDidUpdate hook, I can confirm that sources was correctly updated in the component props. console.log(props) outputs the following: {autoplay: false, controls: true, playbackRates: Array(10), width: "720px", height: "480px", …} Is this approach of attaching the parent state to the VSJ component's sources prop not a valid way to dynamically update the video source? Thx. |
OK, this seemed to do the trick. I just updated the VJS player.src in the componentWillReceiveProps hook: componentWillReceiveProps(props){
} So every time the parent state.sources is updated, it triggers this event but then I read the sources prop and directly set it via this.player. I don't know if this is a garbage way of doing this, but it seems to work based on my limited knowledge of React. If someone has a better and cleaner solution, please do let me know. |
Videojs is working fine when added to html page but when it is added to rectjs component than it is not loading as expected. I have also change class attribute to className. Is there any guideline about how to integrate videojs with reactjs?
P.S. I have tried to find some tutorial for reactjs but couldn't find so.
The text was updated successfully, but these errors were encountered: