I wanted to implement custom play/pause buttons on youtube iframe in a React project but, couldn't achieve it! It returns all type of errors like: When I press my custom mute button, it gives: player.mute is not a function
and so on.
Here is the code I am using:
var tag = document.createElement("script");
tag.src = "https://www.youtube.com/iframe_api";
tag.setAttribute("onload", "onYouTubeIframeReady()");
var firstScriptTag = document.getElementsByTagName("script")[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
var player;
window.onYouTubeIframeReady = function () {
player = new YT.Player("player", {
videoId: "sGPrx9bjgC8",
autoplay: true,
events: {
onReady: onPlayerReady
}
});
};
function onPlayerReady(event) {
event.target.playVideo();
}
const playVid = () => {
player.playVideo();
};
const unMuteVid = () => {
player.unMute();
};
const muteVid = () => {
player.mute();
};
Here is a CodeSandbox .
Any help is greatly appreciated!
Your code is running inside the App component render.
when doing stuff that needs to modify the DOM or relies on an element rendered by the component being present in the DOM you should use the useEffect
hook.
You can in this case move the setup code into a useEffect
and set the player using the useState
hook.
This way you ensure the iframe is mounted and the references will be right.
see it working here: https://codesandbox.io/s/distracted-murdock-o96u5?file=/src/App.js
const [player, setPlayer] = useState();
useEffect(() => {
var tag = document.createElement("script");
tag.src = "https://www.youtube.com/iframe_api";
tag.setAttribute("onload", "onYouTubeIframeReady()");
var firstScriptTag = document.getElementsByTagName("script")[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
window.onYouTubeIframeReady = function () {
setPlayer(
new YT.Player("player", {
videoId: "sGPrx9bjgC8",
autoplay: true,
events: {
onReady: onPlayerReady
}
})
);
};
function onPlayerReady(event) {
event.target.playVideo();
}
}, []);
const playVid = () => {
console.log(player);
player.playVideo();
};
const unMuteVid = () => {
player.unMute();
};
const muteVid = () => {
player.mute();
};
While I'm still unsure of the root cause, it seems that the new YT.Player
is not returning the same object as the one referenced in the onReady event.
One workaround is to just save the event.target reference on the playerReady event to the player variable and use that instead.
function onPlayerReady(event) {
player = event.target;
here it is working: https://codesandbox.io/s/distracted-dream-n2qmi?file=/src/App.js