skip to Main Content

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

2

Answers


  1. 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.

    Login or Signup to reply.
  2. The error message "Unhandled Runtime Error TypeError: Cannot read properties of null (reading ‘playVideo’)" seems to suggest that there’s an issue with the video player initialization.

    It looks like the YouTubePlayer component is being used before it is properly initialized, or it is trying to access the ‘playVideo’ property when the video player is null. Here are a few suggestions to help you fix this issue:

    Ensure that the videoId is not null or undefined before rendering the YouTubePlayer component. You can add a conditional check like this:

    {video.snippet.resourceId.videoId && (
      <YouTubePlayer
        className='video-container'
        videoId={video.snippet.resourceId.videoId}
        opts={opts}
      />
    )}
    

    Make sure that the video player library is properly loaded before using it. You can try wrapping the YouTubePlayer component with the ReactPlayer component from the react-player package. This will load the YouTube iframe API before initializing the player. Here’s an example of how to do that:

    import ReactPlayer from 'react-player/youtube';
    
    // ...
    
    {video.snippet.resourceId.videoId && (
      <ReactPlayer
        className='video-container'
        url={`https://www.youtube.com/watch?v=${video.snippet.resourceId.videoId}`}
        config={{
          youtube: {
            playerVars: {
              autoplay: 0,
            },
          },
        }}
      />
    )}
    

    Make sure you have the react-player package installed. You can install it using npm or yarn:

    npm install react-player
    

    or

    yarn add react-player
    

    These changes should help resolve the error you’re experiencing. If the issue persists, please provide additional information or a more detailed error message, so we can further diagnose the problem.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search