-
Notifications
You must be signed in to change notification settings - Fork 221
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
TypeError: Cannot read properties of null (reading 'src') #413
Comments
+1 to this issue. Having the same behavior when |
I am seeing this also. I wonder if something changed on youtube's side, as that's where the error is actually emitting from:
|
Actually, I just confirmed it's more related this issue: If you unmount the player, then re-mount it, this can happen. The best approach seems to be to keep the player mounted at all times, even if unused. I have had to re-arrange the structure of my react app to do this. |
One other thing I noticed, it seems like this can be caused by timing issues when calling a youtube api function like I have found I can prevent this by waiting until the following is true:
|
Thank you! I tried to check if the player was ready before, but it didn't help. I used what you wrote (and added some of my own) and it seems to work!
|
it happens sometimes and crushes everything. It happens when I try to play a video.
I don't think that the src is in my code, I think it's the library code.
adding the error and my code (long and messy, sorry :( ) below.
I will appreciate any help, thanks in advance.
error - TypeError: Cannot read properties of null (reading 'src')
at X.sendMessage (www-widgetapi.js:203:95)
at Hb (www-widgetapi.js:195:100)
at X.setVolume (www-widgetapi.js:209:157)
at index.jsx:122:28
at commitHookEffectListMount (react-dom_client.js?v=2d8c18c0:16904:34)
at commitPassiveMountOnFiber (react-dom_client.js?v=2d8c18c0:18152:19)
at commitPassiveMountEffects_complete (react-dom_client.js?v=2d8c18c0:18125:17)
at commitPassiveMountEffects_begin (react-dom_client.js?v=2d8c18c0:18115:15)
at commitPassiveMountEffects (react-dom_client.js?v=2d8c18c0:18105:11)
at flushPassiveEffectsImpl (react-dom_client.js?v=2d8c18c0:19486:11).
code - import styles from "./style.module.css";
import YouTube from "react-youtube";
import { useContext, useEffect, useRef, useState } from "react";
import { FaPlay, FaCompressArrowsAlt, FaExpandArrowsAlt } from "react-icons/fa";
import {
TbPlayerSkipForwardFilled,
TbPlayerSkipBackFilled,
TbPlayerPauseFilled,
} from "react-icons/tb";
import { ImVolumeMute2, ImVolumeHigh } from "react-icons/im";
import { BsCameraVideoFill, BsFillCameraVideoOffFill } from "react-icons/bs";
import { Link, useLocation, useNavigate } from "react-router-dom";
import { BsPlusCircle } from "react-icons/bs";
import { IoIosArrowUp, IoIosArrowDown } from "react-icons/io";
import HandlePlayingSongContext from "../../../contexts/HandlePlayingSong";
import AddToPlaylist from "../AddToPlaylist";
import HandleFavoriteSong from "../../HandleFavoriteSong";
import ShowPopups from "../../../contexts/ShowPopups";
import Playlists from "../../../contexts/Playlists";
import Token from "../../../contexts/Token";
function Footer({ backgroundVideo, setBackgroundVideo, screenWidth }) {
const [isPlayerReady, setIsPlayerReady] = useState(false);
const { token } = useContext(Token);
const { playedPlaylist } = useContext(Playlists);
const {
isSongPlaying,
setIsSongPlaying,
songs,
songPlayed,
skipBackOrForward,
} = useContext(HandlePlayingSongContext);
const { showAddToPlaylistPopup, setShowAddToPlaylistPopup } =
useContext(ShowPopups);
const [volume, setVolume] = useState(50);
const [showFooter, setShowFooter] = useState(true);
const [minutes, setMinutes] = useState(0);
const [seconds, setSeconds] = useState(0);
const [songProgress, setSongProgress] = useState(0);
const navigate = useNavigate();
const location = useLocation();
const playerRef = useRef(null);
const opts = {
playerVars: {
autoplay: 1,
// autoplay: 0,
fs: 1,
controls: 0,
disablekb: 1,
modestbranding: 1,
showinfo: 0,
rel: 0,
Loop: 1,
},
};
useEffect(() => {
const params = new URLSearchParams(location.search);
const playSong = params.get("playSong") === "true";
}, [location.search, isPlayerReady]);
const handlePlayerStateChange = (e) => {
let interval;
const handleSongEnd = () => {
clearInterval(interval);
setMinutes(0);
setSeconds(0);
};
if (e.data === window.YT.PlayerState.PLAYING) {
interval = setInterval(() => {
const duration = playerRef?.current?.getDuration();
const currentTime = playerRef?.current?.getCurrentTime();
const progress = (currentTime / duration) * 100;
setSongProgress(progress);
const player = e.target;
const newCurrentTime = player?.getCurrentTime();
const newMinutes = Math.floor(newCurrentTime / 60);
const newSeconds = Math.floor(newCurrentTime % 60);
setMinutes(newMinutes);
setSeconds(newSeconds);
if (currentTime >= duration) {
handleSongEnd();
}
}, 1000);
} else {
clearInterval(interval);
setMinutes(0);
setSeconds(0);
}
};
const handleProgressChange = (e) => {
const progress = parseInt(e.target.value);
const duration = playerRef.current.getDuration();
const seekTime = (progress / 100) * duration;
playerRef.current.seekTo(seekTime);
setSongProgress(progress);
};
const handlePause = () => {
setIsSongPlaying(false);
};
const handlePlay = () => {
setIsSongPlaying(true);
};
useEffect(() => {
console.log(222);
if (isPlayerReady) {
if (playerRef?.current) {
playerRef.current?.setVolume(volume);
if (isSongPlaying) {
playerRef.current?.playVideo();
} else {
playerRef.current?.pauseVideo();
}
}
}
}, [isSongPlaying, volume, songPlayed]);
const handleBackgroundVideo = () => {
setBackgroundVideo((prev) => !prev);
};
const handleVolumeChange = (e) => {
const newVolume = Number(e.target.value);
if (isPlayerReady) setVolume(newVolume);
};
const handleMute = () => {
setVolume(0);
};
const handleUnmute = () => {
setVolume(50);
};
return (
<>
<YouTube
onStateChange={handlePlayerStateChange}
style={{
display:
location.pathname === "/Video" || backgroundVideo
? "block"
: "none",
}}
// videoId={playedPlaylist ? songPlayed?.videoId : songPlayed?.id} old api
videoId={songPlayed?.videoId}
opts={opts}
autoplay
onReady={(e) => {
playerRef.current = e.target;
setMinutes(0);
setSeconds(0);
setIsPlayerReady(true);
}}
onEnd={() => {
playedPlaylist
? skipBackOrForward("forward", playedPlaylist)
: skipBackOrForward("forward", songs);
setMinutes(0);
setSeconds(0);
}}
/>
<div
className={
${styles.arrowButton} ${ !showFooter && styles.arrowUpButton }
}onClick={() => setShowFooter((prev) => !prev)}
>
{showFooter ? : }
{showFooter && (
{location.pathname === "/Video" ? (
<Link
onClick={() => {
navigate(-1);
}}
>
{
<BsFillCameraVideoOffFill
size={25}
style={{ marginLeft: "0.2vw" }}
/>
}
) : (
<Link to={"Video"}>
{
<BsCameraVideoFill
size={25}
style={{
display: screenWidth < 513 && "none",
marginLeft: "0.2vw",
}}
/>
}
)}
{!backgroundVideo && (
<FaExpandArrowsAlt
size={24}
onClick={handleBackgroundVideo}
className={styles.iconButton}
style={{ display: screenWidth < 513 && "none" }}
/>
)}
{backgroundVideo && (
<FaCompressArrowsAlt
size={24}
onClick={handleBackgroundVideo}
className={styles.iconButton}
style={{ display: screenWidth < 513 && "none" }}
/>
)}
<img
className={isSongPlaying ? styles.spinImg : ""}
src={
// playedPlaylist old api
// ? songPlayed?.channelImg
// : songPlayed?.channel?.icon
);
}
export default Footer;
The text was updated successfully, but these errors were encountered: