Reputation: 13
Unhandled Runtime Error TypeError: Cannot read properties of null (reading 'playVideo')
Call Stack eval node_modules/react-youtube/node_modules/youtube-player/dist/index.js (65:0) new Promise
exports.default node_modules/react-youtube/node_modules/youtube-player/dist/index.js (64:0) createPlayer node_modules/react-youtube/dist/YouTube.esm.js (170:41)
https://upload.cc/i1/2023/02/26/daWAmu.png
This error may occur when I click pagination to get the video or just load the page,I show three videos on page, and change the page when want to get more. Sorry for the English not my native language.
React 18.2.0 Next 13.1.6 react-youtube 10.1.0
const Playlist = ({ playlistId }) => {
const [videos, setVideos] = useState([]);
const [currentPage, setCurrentPage] = useState(0);
const isMobile = useMediaQuery({ maxWidth: 640 });
const isPad = useMediaQuery({ maxWidth: 1180 });
const videosPerPage = isMobile ? 1 : isPad ? 2 : 3;
useEffect(() => {
const fetchData = async () => {
try {
const response = await fetch(
`https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&maxResults=50&playlistId=${playlistId}&key=${process.env.NEXT_PUBLIC_ytAPI}`
);
const data = await response.json();
setVideos(data.items);
console.log('data: ', data);
} catch (error) {
console.log(error);
}
};
fetchData();
}, [playlistId]);
const handlePageClick = ({ selected }) => {
setCurrentPage(selected);
};
const currentVideos = useMemo(() => {
const offset = currentPage * videosPerPage;
return videos.slice(offset, offset + videosPerPage);
}, [currentPage, videos, videosPerPage]);
const getOpts = useCallback(() => {
return {
playerVars: {
autoplay: 0,
},
};
}, []);
const opts = getOpts();
return (
<>
<div className='flex container justify-center my-10'>
{currentVideos.map((video) => (
<div
key={video.id}
className='w-full'
>
<YouTubePlayer
className='video-container'
videoId={video.snippet.resourceId.videoId}
opts={opts}
/>
<h2 className='text-center m-4'>{video.snippet.title}</h2>
</div>
))}
</div>
<ReactPaginate
className='item flex w-full justify-center mb-8'
previousLabel={'« prev'}
nextLabel={'next »'}
breakLabel={'...'}
marginPagesDisplayed={0}
activeClassName={'active'}
breakClassName={'disabled'}
containerClassName={'pagination'}
pageCount={Math.ceil(videos.length / videosPerPage)}
onPageChange={handlePageClick}
forcePage={currentPage}
pageRangeDisplayed={3}
/>
</>
);
};
export default Playlist;
I tried to replace react-youtube with react-player but got the same error message so I think it might not be caused by npm package
Upvotes: 1
Views: 1136
Reputation: 460
You probably have to wait for the fetch request to the API. You can restructure your code like this:
const Playlist = ({ playlistId }) => {
const [videos, setVideos] = useState([]);
const [isLoading, setIsLoading] = useState(true);
// ...
useEffect(() => {
const fetchData = async () => {
try {
const response = await fetch(
`https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&maxResults=50&playlistId=${playlistId}&key=${process.env.NEXT_PUBLIC_ytAPI}`
);
const data = await response.json();
setVideos(data.items);
setIsLoading(false); // set isLoading to false after data is fetched
} catch (error) {
console.log(error);
setIsLoading(false); // also set isLoading to false on error
}
};
fetchData();
}, [playlistId]);
// ...
return (
<>
{isLoading ? (
<div>Loading...</div>
) : (
<div className='flex container justify-center my-10'>
{currentVideos.map((video) => (
<div key={video.id} className='w-full'>
<YouTubePlayer
className='video-container'
videoId={video.snippet.resourceId.videoId}
opts={opts}
/>
<h2 className='text-center m-4'>{video.snippet.title}</h2>
</div>
))}
</div>
)}
{/* ... */}
</>
);
};
Now it shows Loading...
until you get a response from the API.
Upvotes: 0