Having error Uncaught (in promise) TypeError: Cannot read properties of null (reading 'addEventListener') at webviewer.min.js:1:25977

WebViewer Version:8.11.0

Do you have an issue with a specific file(s)? webviewer.min.js
Can you reproduce using one of our samples or online demos? no
Are you using the WebViewer server? no
Does the issue only happen on certain browsers? no
Is your issue related to a front-end framework? yes next.js
Is your issue related to annotations? no

Please give a brief summary of your issue:
(Think of this as an email subject)
having error while loading webviewer cannot read properties of null (reading ‘addEventListener’)

Please describe your issue and provide steps to reproduce it:
(The more descriptive your answer, the faster we are able to help you)
when opening a document from external url the error is coming cannot read properties of null (reading ‘addEventListener’)

Please provide a link to a minimal sample where the issue is reproducible:

import('@pdftron/webviewer').then(() => {
      WebViewer(
        {
          path: '/WebViewer/lib',
          initialDoc: meta.data.image,
		  showLocalFilePicker: true,
			fullAPI: true,
		}, viewer.current ).then(async(instance) => {
			
			const { UI, Core } = instance;
	
    const { documentViewer, annotationManager, Tools, Annotations } = Core;
    // call methods from UI, Core, documentViewer and annotationManager as needed

    const existingPdfBytes1 = await fetch(meta.data.image).then(res => res.blob())
    // perform the conversion with no optional parameters
	
      const buf = await Core.officeToPDFBuffer(existingPdfBytes1);
	  
	  //optionally save the blob to a file or upload to a server
      const blob = new Blob([buf], { type: 'application/pdf' });

    instance.UI.loadDocument(blob);
	
	const reader = new FileReader();
	reader.readAsArrayBuffer(blob);
      reader.onload = async() => {
		  const pdfDoc = await PDFDocument.load(reader.result)
			const page = pdfDoc.addPage()
			page.drawText('Hash URL:'+meta.data.image, { x: 50, y: 700, size: 10 })
			
			pdfDoc.setTitle(meta.data.image);
				const pdfDataUri1 = await pdfDoc.saveAsBase64({ dataUri: true });
		setPdfInfo(pdfDataUri1);
	  };
	})
	});
  }

Hello,

Thank you for contacting WebViewer support.

Unfortunately, I was not able to reproduce your issue locally. I’d like to ask you if it would be possible for you to clone our Next.js sample and paste the code you shared with us, with the external URL and send it back to us. If you prefer, you can also send us a staging project that we can access.

If we have this, we can better assess and troubleshoot the issue for you.

Best,

Dandara Navarro
Web Software Developer
PDFTron Systems, Inc.

Hi Mr. Dandara Navarro, Thanks for your reply. I cannot copy the code in your Next.js sample because it’s a blockchain project and contains many other npm modules which will be too much work to copy everything there. but I will paste the complete file code and I can also add you to our private repository if you want. It is a commercial project and I can’t make this code public. But I really need your help as I know it’s a small bug I just can’t figure it out. Below is the complete code if it helps or I can add you to the private repo on github. Thanks and awaiting for your reply.

import {useRouter} from 'next/router'
import { ethers } from 'ethers'
import { useEffect, useState, useRef } from 'react'
import Head from "next/head";
import { ThemeProvider } from "styled-components";
import Footer from "../../../src/sections/Footer";
import theme from "../../../src/assets/theme/theme";
import GlobalStyle from "../../../src/assets/theme/private";
import axios from 'axios'
import { PDFDocument, StandardFonts } from 'pdf-lib'
import Web3Modal from "web3modal"
import Link from 'next/link'
import Fortmatic from "fortmatic"
import {
  marketplaceAddress
} from '../../../config2'

import NFTMarketplace from '../../../artifacts/contracts/NFTMarketplace.sol/NFTMarketplace.json'

let rpcEndpoint = 'https://polygon-mainnet.infura.io/v3/d667821959a14f63aca5691e56941387'

if (process.env.NEXT_PUBLIC_WORKSPACE_URL2) {
  rpcEndpoint = process.env.NEXT_PUBLIC_WORKSPACE_URL2
}

export default function Home() {
    const router = useRouter();
    const {nftId} = router.query;
    const {projectId,setprojectId} = useState(nftId)
	const [called, setCalled] = useState(false)
	const [pdfDataUri, setPdfInfo] = useState('');
    const [nfts, setNfts] = useState([])
    const [provisions, setProvisions] = useState([])
    const [loadingState, setLoadingState] = useState('not-loaded')
    const [formInput, updateFormInput] = useState({ bidprice: '' })
	const viewer = useRef('viewer');
    useEffect(async() => {
      const customNetworkOptions = {
        rpcUrl: 'https://polygon-mainnet.infura.io/v3/d667821959a14f63aca5691e56941387',
        chainId: 137
      }

    const providerOptions = {
      fortmatic: {
        package: Fortmatic, // required
        options: {
          key: "pk_live_63EF2259C50D5BC4", // required,
          network: customNetworkOptions // if we don't pass it, it will default to localhost:8454
        }
      }
    };

    const web3Modal = new Web3Modal({
      network: "polygon-mainnet", // optional
      cacheProvider: true, // optional
      providerOptions // required
    });
    const connection = await web3Modal.connect()
    const user = await connection.fm.user.getUser()
    console.log('user email '+user.email);
    const provider = new ethers.providers.Web3Provider(connection)    
    const signer = provider.getSigner()
    const projectId = window.location.pathname.split("/")[3];
    const contract = new ethers.Contract(marketplaceAddress, NFTMarketplace.abi, signer)
    let listingPrice = await contract.getListingPrice()
    listingPrice = listingPrice.toString()
    let depemail = await contract.getdepemail(projectId)
    depemail = depemail.toString()
    console.log('depemail '+ depemail);
	let tokenId = await contract.getprojectTokenId(projectId);
    tokenId = tokenId.toNumber()
    
    /* next, create the item */
    //contract = new ethers.Contract(marketplaceAddress, NFTMarketplace.abi, provider)
    
    const tokenUri = await contract.tokenURI(tokenId)
    const meta = await axios.get(tokenUri)
	
  const existingPdfBytes = await fetch(meta.data.image).then(res => res.arrayBuffer())
  try {
  const pdfDoc = await PDFDocument.load(existingPdfBytes)
  const page = pdfDoc.addPage()
  page.drawText('Hash URL:'+meta.data.image, { x: 50, y: 700, size: 10 })
  pdfDoc.setTitle(meta.data.image);
  const pdfDataUri1 = await pdfDoc.saveAsBase64({ dataUri: true });
  setPdfInfo(pdfDataUri1);
  }
  catch(e) {
	import('@pdftron/webviewer').then(() => {
      WebViewer(
        {
          path: '/WebViewer/lib',
          initialDoc: meta.data.image,
		  showLocalFilePicker: true,
			fullAPI: true,
		}, viewer.current ).then(async(instance) => {
			
			const { UI, Core } = instance;
	
    const { documentViewer, annotationManager, Tools, Annotations } = Core;
    // call methods from UI, Core, documentViewer and annotationManager as needed

    const existingPdfBytes1 = await fetch(meta.data.image).then(res => res.blob())
    // perform the conversion with no optional parameters
	
      const buf = await Core.officeToPDFBuffer(existingPdfBytes1);
	  
	  //optionally save the blob to a file or upload to a server
      const blob = new Blob([buf], { type: 'application/pdf' });

    instance.UI.loadDocument(blob);
	
	const reader = new FileReader();
	reader.readAsArrayBuffer(blob);
      reader.onload = async() => {
		  const pdfDoc = await PDFDocument.load(reader.result)
			const page = pdfDoc.addPage()
			page.drawText('Hash URL:'+meta.data.image, { x: 50, y: 700, size: 10 })
			
			pdfDoc.setTitle(meta.data.image);
				const pdfDataUri1 = await pdfDoc.saveAsBase64({ dataUri: true });
		setPdfInfo(pdfDataUri1);
	  };
	})
	});
  }
    if(user.email===depemail) {
      loadNFTs();
	  connect();
    }
    }, [])
    async function loadNFTs() { 
        
        
        const provider = new ethers.providers.JsonRpcProvider(rpcEndpoint)
        const contract = new ethers.Contract(marketplaceAddress, NFTMarketplace.abi, provider)
        const data = await contract.fetchMarketItems()
        console.log('data')
        console.log(data)
        const items = await Promise.all(data.map(async i => {
            console.log("nftid "+nftId);
          const tokenUri = await contract.tokenURI(i.tokenId)
          const meta = await axios.get(tokenUri)
          let price = ethers.utils.formatUnits(i.price.toString(), 'ether')
          let item = {
            price,
            projectId: i.projectId.toNumber(),
            seller: i.seller,
            owner: i.owner,
            image: meta.data.image,
            name: meta.data.name,
            description: meta.data.description,
            depemail:i.depemail
          }
          return item
          
        }))
        console.log('items-project')
        console.log(items)
        setNfts(items)
       
      }
      
	  async function connect() {
    // Example for kovan:
    const customNetworkOptions = {
      rpcUrl: 'https://polygon-mainnet.infura.io/v3/d667821959a14f63aca5691e56941387',
      chainId: 137
    }

    const providerOptions = {
      fortmatic: {
        package: Fortmatic, // required
        options: {
          key: "pk_live_63EF2259C50D5BC4", // required,
          network: customNetworkOptions // if we don't pass it, it will default to localhost:8454
        }
      }
    };

    const web3Modal = new Web3Modal({
      network: "polygon-mainnet", // optional
      cacheProvider: true, // optional
      providerOptions // required
    });
    setCalled(true);
	if(called===true) return false;
    const instance = await web3Modal.connect();
    const user = await instance.fm.user.getUser();
    
    const provider = new ethers.providers.Web3Provider(instance);
    const signer = provider.getSigner();
    const address = await signer.getAddress();
    const balance = await provider.getBalance(address);
	let balance1 = ethers.utils.formatEther(balance);
	console.log(balance1);
	// Sender private key: 
	// correspondence address 0xb985d345c4bb8121cE2d18583b2a28e98D56d04b
	let privateKey = 'xxxxxxx'
	
	// Create a wallet instance
    let wallet = new ethers.Wallet(privateKey, provider)
	
	// Receiver Address which receives Ether
	let receiverAddress = address
	// Ether amount to send
	let amountInEther = '0.1'
	const feeData = await provider.getFeeData()
	// Create a transaction object
	console.log(ethers.utils.formatEther(feeData.gasPrice));
	let tx = {
    to: receiverAddress,
    // Convert currency unit from ether to wei
    value: ethers.utils.parseEther(amountInEther),
	gasPrice:'40000000000'
	}
	// Send a transaction
	if(balance1<=0.03){
	wallet.sendTransaction(tx)
	.then((txObj) => {
    console.log('txHash', txObj.hash)
    // => 0x9c172314a693b94853b49dc057cf1cb8e529f29ce0272f451eea8f5741aa9b58
    // A transaction result can be checked in a etherscan with a transaction hash which can be obtained here.
	})
	}
    const data = {
      toemail: user.email, // Change to your recipient
      name: 'True Contracts',
      email: 'info@truecontracts.io', // Change to your verified sender
      subject: 'Login message',
      message: 'Hi this is to remind you that you have successfully logged in fortmatic with email '+user.email
            +' and your wallet address is '+address,
      html: '<strong>Hi this is to remind you that you have successfully logged in fortmatic with email '+user.email
            +' and your wallet address is '+address+ '</strong>',
    }
    try {
      await fetch("/api/contact", {
        "method": "POST",
        "headers": { "content-type": "application/json" },
        "body": JSON.stringify(data)
      })

            //if sucess do whatever you like, i.e toast notification
    
    } catch (error) {
        // toast error message. whatever you wish 
        console.log('toast error');
    }
	const data1 = {
      toemail: 'catchall@truecontracts.io', // Change to your recipient
      name: 'True Contracts',
      email: 'info@truecontracts.io', // Change to your verified sender
      subject: 'Login message from email '+user.email,
      message: 'Hi this is to remind you that you have successfully logged in fortmatic with email '+user.email
            +' and your wallet address is '+address,
      html: '<strong>Hi this is to remind you that you have successfully logged in fortmatic with email '+user.email
            +' and your wallet address is '+address+ '</strong>',
    }
    try {
      await fetch("/api/contact", {
        "method": "POST",
        "headers": { "content-type": "application/json" },
        "body": JSON.stringify(data1)
      })

            //if sucess do whatever you like, i.e toast notification
    
    } catch (error) {
        // toast error message. whatever you wish 
        console.log('toast error');
    }
    document.getElementById('connect_lib').innerText = 'connected';
    if(user.email=='department@truecontracts.io') {
      document.getElementById('create').style.display = 'block';
    }
  }
      if (loadingState === 'loaded' && !nfts.length) return (<h1 className="px-20 py-10 text-3xl">please wait projects are loading</h1>)
      return (
        <ThemeProvider theme={theme}>
      <Head>
        <title>True Contracts</title>
        <meta name="Description" content="React next landing page" />
        <meta name="theme-color" content="#280D57" />
        {/*<link rel="shortcut icon" type="image/x-icon" href={FavIcon} />*/}
      </Head>

      <GlobalStyle />
	  <nav className="border-b p-6">
        <p className="text-4xl font-bold text-white">True Contracts</p>
        <div className="flex mt-4">
          <Link href="/private/projects">
            <a className="mr-4 text-white">
              Projects
            </a>
          </Link>
          <Link href="/private/create-item">
            <a className="mr-6 text-black hidden" id="create">
              Create a Document
            </a>
          </Link>
          {/*<Link href="/my-assets">
            <a className="mr-6 text-pink-500">
              My Contracts
            </a>
          </Link>
          <Link href="/creator-dashboard">
            <a className="mr-6 text-pink-500">
              Projects Dashboard
            </a>
  </Link>*/}
        
        </div>
       
      </nav>
      <button className='float-right absolute top-16 right-0 bg-pink-500 rounded py-2 px-12 text-white' id="connect_lib" onClick={connect}>connect</button>
        <div className="flex justify-center">
          <div className="px-4" style={{ maxWidth: '1600px' }}>
            <div className="grid grid-cols-1 sm:grid-cols-1 lg:grid-cols-1 gap-4 pt-4">
              {
                nfts.map((nft, i) => (
                  nft.projectId==nftId &&
                  <div key={i} className="border shadow rounded-xl overflow-hidden">
                    <iframe src={pdfDataUri} id="showpdf" type="application/pdf" width="1100" height="600">
                    
                    </iframe>
					
					<div className='webviewer' id="viewer" ref={viewer} style={{ height: '100vh' }}></div>
					
                    <div className="p-4">
                      <p style={{ height: '64px' }} className="text-2xl font-semibold text-white">{nft.name}</p>
                      <div>
                        <p className="text-gray-400">{nft.description}</p>
						<p>download document file: <a href={pdfDataUri} download="downpdf.pdf">click here</a></p>
                      </div>
                    </div>
                    <div className="p-4 bg-black">
                      <p className="text-2xl mb-4 font-bold text-white hidden">{nft.price} ETH</p>
                      <p className="text-2xl mb-4 font-bold text-white">uploader</p>
                      <p className="text-2xl mb-4 font-bold text-white">{nft.depemail}</p>
                      
                      

                    </div>
                  </div>
                ))
              }
            </div>
          </div>
        </div>
        </ThemeProvider>
      )
    }

Hello,

My sincere apologies for the late response. I would appreciate it if you could add me to your project. Unfortunately, it is very difficult to know why the element is undefined without the application running. Does your project has the README file with the instructions on how to run it? If not, I’d like to ask you to help me with these instructions.

And just to confirm, is this issue happening only with external URLs?

Best,

Dandara Navarro
Web Software Developer
PDFTron Systems, Inc.

Hi there,

I had the same error on the browser console. The problem was that viewer.current returned null in the first useEffect. Check the valid value in effect and if it’s null, run effect when you know, that viewer ref is correctly initialized. I have no idea if it is the same case, but maybe it will help someone.

Best regards,
Dorota