dosebot
dosebot

Reputation: 121

Using Vidyard embedded player inside of React

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

Answers (3)

Emanuel Adrian Lucaci
Emanuel Adrian Lucaci

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

Alfonso
Alfonso

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

jP_
jP_

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

Related Questions