Skip to content

Instantly share code, notes, and snippets.

@kenyk7
Last active November 6, 2024 21:17
Show Gist options
  • Select an option

  • Save kenyk7/cc1bd9e089975fa619128074efa66e31 to your computer and use it in GitHub Desktop.

Select an option

Save kenyk7/cc1bd9e089975fa619128074efa66e31 to your computer and use it in GitHub Desktop.
Youtube Basic React Component
import {
forwardRef,
useCallback,
useEffect,
useImperativeHandle,
useRef,
useState,
} from 'react';
import type { Ref } from 'react';
declare global {
// eslint-disable-next-line
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 {
// eslint-disable-next-line
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
onStateChange?: (e: YoutubeStateChangeEvent) => void;
playerVars?: PlayerVars;
}
const defaultProps: YoutubePropsO = {
width: '480',
height: '320',
playerVars: {
controls: 1,
showinfo: 0,
autoplay: 0,
loop: 0,
rel: 0,
},
};
type YoutubeProps = YoutubePropsR & YoutubePropsO;
export const Youtube = forwardRef(
(
{
videoId,
width = defaultProps.width,
height = defaultProps.height,
onReady = undefined,
onStateChange = undefined,
playerVars = defaultProps.playerVars,
}: YoutubeProps,
ref: Ref<YoutubeRef> // same interface for parent ref
) => {
const youtubeRef = useRef(null);
// eslint-disable-next-line
const [youtubePlayer, setYoutubePlayer] = useState<any>();
useImperativeHandle(ref, () => ({
player: () => youtubePlayer,
}));
const initPlayer = useCallback(() => {
// 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);
}, [videoId, width, height, playerVars, onReady, onStateChange]);
useEffect(() => {
const id = 'youtube-script-js-player_api';
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 if (!youtubePlayer) {
initPlayer();
}
}, [youtubePlayer]);
return <div ref={youtubeRef} />;
}
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment