Skip to content

Instantly share code, notes, and snippets.

@kenyk7
Last active September 21, 2023 13:42
Show Gist options
  • Save kenyk7/cc1bd9e089975fa619128074efa66e31 to your computer and use it in GitHub Desktop.
Save kenyk7/cc1bd9e089975fa619128074efa66e31 to your computer and use it in GitHub Desktop.
Youtube Basic React Component
/* eslint-disable @typescript-eslint/no-explicit-any */
import {
forwardRef,
Ref,
useEffect,
useImperativeHandle,
useRef,
useState,
} from 'react';
declare global {
const YT: any;
interface Window {
onYouTubePlayerAPIReady: () => void;
}
}
// https://developers.google.com/youtube/iframe_api_reference?hl=es-419#Events
export interface YoutubeStateChangeEvent {
// basic StateChangeEvent
data: number;
}
export interface YoutubeRef {
player: any;
// see options: https://developers.google.com/youtube/iframe_api_reference?hl=es-419#Playback_controls
}
interface YoutubePropsR {
videoId: string;
}
type YtVar = 0 | 1;
interface PlayerVars {
controls?: YtVar;
showinfo?: YtVar;
autoplay?: YtVar;
loop?: YtVar;
rel?: YtVar;
}
interface YoutubePropsO {
width?: string;
height?: string;
onReady?: () => void;
// eslint-disable-next-line no-unused-vars
onStateChange?: (e: YoutubeStateChangeEvent) => void;
playerVars?: PlayerVars;
}
const defaultProps: YoutubePropsO = {
width: '480',
height: '320',
onReady: undefined,
onStateChange: undefined,
playerVars: {
controls: 1,
showinfo: 0,
autoplay: 0,
loop: 0,
rel: 0,
},
};
type YoutubeProps = YoutubePropsR & YoutubePropsO;
const id = 'youtube-script-js-player_api';
const Youtube = forwardRef(
(
{
videoId,
width,
height,
onReady,
onStateChange,
playerVars,
}: YoutubeProps,
ref: Ref<YoutubeRef> // same interface for parent ref
) => {
const youtubeRef = useRef(null);
const [youtubePlayer, setYoutubePlayer] = useState<any>();
useImperativeHandle(ref, () => ({
player: () => youtubePlayer,
}));
const initPlayer = () => {
// eslint-disable-next-line
const player = new YT.Player(youtubeRef.current, {
width,
height,
videoId,
playerVars: {
playlist: videoId, // hack for loop
...defaultProps.playerVars,
...playerVars,
},
events: {
onReady,
onStateChange,
},
});
setYoutubePlayer(player);
};
useEffect(() => {
let tag = document.getElementById(id) as HTMLScriptElement;
if (!tag) {
tag = document.createElement('script');
tag.id = id;
tag.src = 'https://www.youtube.com/player_api';
const firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode?.insertBefore(tag, firstScriptTag);
window.onYouTubePlayerAPIReady = () => {
initPlayer();
};
} else {
const tId = setInterval(() => {
// eslint-disable-next-line no-undef
if (typeof YT !== 'undefined' && typeof YT.Player !== 'undefined') {
initPlayer();
clearInterval(tId);
}
}, 250);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
return <div ref={youtubeRef} />;
}
);
Youtube.defaultProps = defaultProps;
export default Youtube;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment