Skip to main content

React.js

Try out Source Embedder in your React project.

Replit Example

index.html

Add the following script tag to your index.html file.

<script src="https://embed.sourcesync.io" defer></script>
SourceEmbedVideo.tsx - An example video component powered by Source Embedder
import React, { useRef, useEffect, useState, useImperativeHandle, forwardRef } from 'react';

declare global {
interface Window {
SourceEmbedsLoader: {
load: (opts?: { version?: string }) => Promise<any>
}
}
}

/**
* Helper function to obtain Source Embedder instance
*/
function getEmbedderAsync(baseSettings: any = {}, loaderOpts: any = {}) {
return new Promise(async (resolve) => {
const sourceEmbedder = await window.SourceEmbedsLoader.load(loaderOpts)
const embedderInstance = sourceEmbedder.register(baseSettings)
return resolve(embedderInstance)
})
}

/**
* Exposed functions
*/
export interface SourceEmbedVideoRef {
show: () => void
hide: () => void
}

/**
* Component props
*/
interface AdditionalSourceEmbedVideoProps {
embedSettings: { distributionId: string } & any
}
export type SourceEmbedVideoProps = React.VideoHTMLAttributes<HTMLVideoElement> & AdditionalSourceEmbedVideoProps

const SourceEmbedVideo = forwardRef<SourceEmbedVideoRef, SourceEmbedVideoProps>((props, ref) => {
const { embedSettings, ...videoAttrs } = props
const videoRef = useRef<HTMLVideoElement>(null);
const [isInitialized, setIsInitialized] = useState(false);
const [embedInstance, setEmbedInstance] = useState<any>(null);
// ensure useEffect is called only once with <React.StrictMode>
let mounted: boolean = true

// load embedder once on mount
useEffect(() => {
if (videoRef.current == null || isInitialized || mounted === false) return
setIsInitialized(true)
const setupEmbedder = async () => {
const embedder: any = await getEmbedderAsync();
await embedder.embed({
strategy: "direct-iframeless",
...embedSettings,
el: videoRef.current
});
setEmbedInstance(embedder.getInstance(videoRef.current));
};
setupEmbedder();

return () => {
mounted = false
embedInstance?.destroy?.();
};
}, [isInitialized]);

const show = () => { embedInstance?.show?.() };
const hide = () => { embedInstance?.hide?.() };

useImperativeHandle(ref, () => ({ show, hide }))

return (
<video ref={videoRef} {...videoAttrs}>
{props.children}
</video>
);
});

export default SourceEmbedVideo;

App.tsx - An example usage of SourceEmbedVideo.tsx
import { useRef, ElementRef } from 'react'
import SourceEmbedVideo from './SourceEmbedVideo'

export default function App() {
const embedVideoRef = useRef<ElementRef<typeof SourceEmbedVideo>>(null)

return (
<main>
<SourceEmbedVideo
ref={embedVideoRef}
src="https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4"
style={{ width: '100%' }}
embedSettings={{
distributionId: 'getting-started',
// other configurations...
}}
controls
/>
<div>
<button onClick={() => embedVideoRef.current?.show?.()}>show</button>
<button onClick={() => embedVideoRef.current?.hide?.()}>hide</button>
</div>
</main>
)
}