I've been tasked with inserting an embedded "Vidyard" video into a React project.
The embed code looks something like this.
<script type="text/javascript" async
src="https://play.vidyard.com/embed/v4.js">
</script>
<img
style="width: 100%; margin: auto; display: block;"
class="vidyard-player-embed"
src="xxxx"
data-uuid="xxxx"
data-v="4"
data-type="inline"
/>
This does not work 100% of the time.
When I insert this into a plain .html file, the video shows up.
On the plain .html file, the image loads and I believe the script then finds the image and drops the embedded video player on the DOM from there.
What I believe is happening is that there is a conflict between React/Vidyard as far as manipulating the DOM.
I've attempted to drop this directly into a component with no luck.
I've also added the script call directly to the <head>.
I've followed Script load in react and attempted to manually call the script file, I also stuck the manual script load in both the componentWillMount and componentDidMount.
I've also inserted the code into dangerouslySetInnerHTML.
The behavior remains the same.
Ideally if this was to work the image would append to the page. The embed/v4.js script would then append a embedded video player on the image. Currently, the image appears and does not get switched out to a video. If i refresh/hard refresh the page, sometimes the image will swap out for the embedded video player.
Here's my solution for those who prefer hooks/functional components:
import React from "react"
import ScriptLoader from "react-script-loader-hoc"
const VIDYARD_EMBED_JS_URL = "https://play.vidyard.com/embed/v4.js"
function VidyardPlayer(props: {
scriptsLoadedSuccessfully: boolean
maxWidth: string
maxHeight: string
type: string
uuid: string
aspect?: "4:3" | "16:9" | "16:10"
onLoadCallback?: (player: any, embedApi: any) => void
}) {
const {
scriptsLoadedSuccessfully,
maxWidth,
maxHeight,
type,
uuid,
aspect,
onLoadCallback,
} = props
const containerRef = React.useRef<any>()
React.useEffect(() => {
if (scriptsLoadedSuccessfully) {
window.VidyardV4.api
.renderPlayer({
aspect,
container: containerRef.current,
height: maxHeight,
type,
uuid,
width: maxWidth,
})
.then((player: any) => {
if (onLoadCallback) {
onLoadCallback(player, window.VidyardV4.api)
}
})
.catch((e: any) => {
// eslint-disable-next-line no-console
console.error(e.message)
})
}
}, [scriptsLoadedSuccessfully])
return <div ref={containerRef} />
}
export default ScriptLoader(VIDYARD_EMBED_JS_URL)(VidyardPlayer)
I finally found a solution for the same problem. Here's the player component that you can import and just pass the video id.
/* eslint-disable */
import * as React from 'react';
let vidyardEmbed = {};
if (typeof window !== 'undefined') {
vidyardEmbed = require('../../../utils/vidyard');
}
export default class VidyardEmbed extends React.Component {
constructor() {
super(...arguments);
this.state = { hasError: false };
this.handleContainerRef = ref => {
if (ref) {
this.container = ref;
}
};
}
componentDidMount() {
if (!this.container) {
return;
}
if (this.props.playbackUrl) {
vidyardEmbed._debug.setPlaybackURL(this.props.playbackUrl);
}
vidyardEmbed.api
.renderPlayer(
Object.assign(
{
aspect: this.props.aspect,
container: this.container,
height: this.props.maxHeight,
type: this.props.type,
uuid: this.props.uuid,
width: this.props.maxWidth
},
this.props.params
)
)
.then(player => {
this.player = player;
if (typeof this.props.api === 'function') {
this.props.api(player, vidyardEmbed.api);
}
})
.catch(e => {
this.setState({ hasError: true });
console.warn(e.message);
});
}
componentWillUnmount() {
if (this.player) {
vidyardEmbed.api.destroyPlayer(this.player);
}
}
render() {
return <div ref={this.handleContainerRef} />;
}
}
The imported vidyard file is the script that they offer but I imported it locally. That way I was able to get it working within React without any issues.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With