Reputation: 121
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.
Upvotes: 4
Views: 1919
Reputation: 41
try running this after the page is loaded:
vidyardEmbed.api.renderDOMPlayers();
You can find more information how vidyard works here:
https://developer.vidyard.com/responsive-player-embed-api.html
Upvotes: 0
Reputation: 1325
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)
Upvotes: 3
Reputation: 151
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.
Upvotes: 1