I have 2 components -> a) VideoJSPlayer and b) VideosPage.
As the name suggests, VideoJsPlayer has the video player part (using videojs) and VideosPage shows videos using VideoJsPlayer component.
The code for each of the components is:
a) VideoJsPlayer
import React, { useEffect } from "react";
import videojs from "video.js";
const VideoJsPlayer = props => {
let player = null;
let videoNode = null;
// Effect for first render only.
useEffect(() => {
player = videojs(videoNode, props, function onPlayerReady() {
console.log("onPlayerReady");
});
return function cleanup() {
if (player) {
player.dispose();
}
};
}, []);
return (
<div>
<div data-vjs-player>
<video ref={node => (videoNode = node)} className="video-js"></video>
</div>
</div>
);
};
export default VideoJsPlayer;
b) VideosPage
import React, { useState, useEffect } from "react";
import videojs from "video.js";
import VideoJsPlayer from "../../components/VideoJsPlayer";
const VideosPage = props => {
const [videoJsOptions, setVideoJsOptions] = useState({});
// Effect for first render only.
useEffect(() => {
let videoJsOptionsTest = {
autoplay: false,
controls: true,
sources: [
{
src: "/my-video.mp4",
type: "video/mp4"
}
]
};
console.log("test");
setVideoJsOptions(videoJsOptionsTest);
// Cleanup on unmount.
return function cleanup() {};
}, []);
return (
<React.Fragment>
<VideoJsPlayer {...videoJsOptions} />
</React.Fragment>
);
};
export default VideosPage;
When I check the URL which renders the VideosPage component, I don't see any video. I'm assuming the state (videoJsOptions) is not yet updated in VideosPage and hence I don't see the video. I can see the console log - "test" though.
When I change the code of VideosPage to:
import React, { useState, useEffect } from "react";
import videojs from "video.js";
import VideoJsPlayer from "../../components/VideoJsPlayer";
const VideosPage = props => {
const [videoJsOptions, setVideoJsOptions] = useState({
autoplay: false,
controls: true,
sources: [
{
src: "/my-video.mp4",
type: "video/mp4"
}
]
});
// Effect for first render only.
useEffect(() => {
/*
let videoJsOptionsTest = {
autoplay: false,
controls: true,
sources: [
{
src: "/my-video.mp4",
type: "video/mp4"
}
]
};
console.log("test");
setVideoJsOptions(videoJsOptionsTest);
*/
// Cleanup on unmount.
return function cleanup() {};
}, []);
return (
<React.Fragment>
<VideoJsPlayer {...videoJsOptions} />
</React.Fragment>
);
};
export default VideosPage;
Now when I check the URL which renders the VideosPage component, I see the video.
My assumption is - In the first case, the state update is queued and never happens. Because if it did happen, it should have re-rendered the component and I should have seen my video.
I have also tried updating useEffect in VideoJSPlayer to run every time props changes, but it didn't help.
Any insights on this?
Thank you for your time.
Here is a sandbox : codesandbox
You have some mistakes:
videoNode
like that because Video.js uses Ref
and since you are using React hooks you need to use useRefimport React, { useRef, useEffect } from "react"
const VideoJsPlayer = props => {
const videoRef = useRef(null)
useEffect(() => {
//...
videojs(
videoRef.current,
props,
function onPlayerReady() {
console.log("onPlayerReady")
}
)
//...
}, [])
return (
<video ref={videoRef} className="video-js" />
)
}
useEffect
again in your VideosPage
component since its already been used inside your VideoJsPlayer
component. Your initial options need to set directly in the state
or outside the function like so:const initialOptions = {
// ...
}
const VideosPage = () => {
return <VideoJsPlayer {...initialOptions} />
}
Here is a working codeSandbox example based on your code.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.