1

I'm trying to create a PDF viewer on my nextjs static page but i dont know how! hope you guys can help me solving this error or showing one other way to do this. (I'm new to Next.js) I was following this working example here

index.js

import SiteLayout from "../../components/SiteLayout";
import React from 'react';
import ReactDOM from "react-dom";
import Viewer from "../resume/viewer.js";

export default function Resume({ resume }) {
  return (   
    <div>
      <Viewer />
    </div> 
  );
}

viewer.js

import React, { useRef, useEffect } from "react";
import WebViewer from "@pdftron/webviewer";

const Viewer = (props) => {
  const viewer = useRef(null);

  useEffect(() => {       
    WebViewer({
      path: "/lib",
      initialDoc: "/pdf/GustavoMorilla.pdf"
    }, viewer.current);
  }, []);

  return (
    <div className="Viewer">
      <div className="header">React sample</div>
      <div className="webviewer" ref={viewer}></div>
    </div>
  );
};

export default Viewer;
Gustavo Morilla
  • 192
  • 1
  • 1
  • 9
  • Where are you rendering Resume? You are getting the error because of this ReactDOM.render() – lissettdm Mar 29 '21 at 19:20
  • for a Navbar item "resume" the user will be redirected to this page via "href" ... I need a way to load the page and call the Viewer component that contains the webviewer. Dont know if this react DOM declaration is correct. – Gustavo Morilla Mar 29 '21 at 19:26
  • Why do you use ReactDOM.render( instead of ? – lissettdm Mar 29 '21 at 19:28
  • Are you missing to pass viewer.current as second argument in WebViewer function? – lissettdm Mar 29 '21 at 19:38
  • Try to add more details about the error (line, file, etc) because I don't see anything wrong – lissettdm Mar 29 '21 at 19:50
  • ReferenceError: window is not defined at Object. (C:\Users\Gustavo Morilla\MyProfile\node_modules\@pdftron\webviewer\webviewer.min.js:1:224) at Module._compile (internal/modules/cjs/loader.js:1063:30) at Object.Module._extensions..js (internal/modules/cjs/loader.js:1092:10) at Module.load (internal/modules/cjs/loader.js:928:32) at Function.Module._load (internal/modules/cjs/loader.js:769:14)..... – Gustavo Morilla Mar 29 '21 at 19:52
  • I think that just importing the function is causing the error, the solution will be to import the function inside useEffect. – lissettdm Mar 29 '21 at 20:26

3 Answers3

2

WebViewer needs the window object to work. In nextjs there is a prerender phase server side and on that side window is not defined.

To solve your problem you can use next/dynamic in viewer.js

import dynamic from 'next/dynamic';
const WebViewer = dynamic(() => import('@pdftron/webviewer'), {ssr: false});

Alternatively you can import Viewer in index.js with dynamic import

import dynamic from 'next/dynamic';
const Viewer = dynamic(() => import('../resume/viewer.js'), {ssr: false});
dna
  • 2,097
  • 1
  • 11
  • 35
  • But useEffect will runs in client side, not server side, and he is calling WebViewer inside useEffect, or just importing the function will causes some code runs – lissettdm Mar 29 '21 at 20:21
  • The import (and ssr) is at component level. I see the same error many times in nextjs applications and the response Is always the same :) – dna Mar 29 '21 at 20:29
  • 1
    Thanks dna! my code finally works fine. I never used the dynamic imports before and now i see one environment where its necessary. Its simple but thanks again. – Gustavo Morilla Mar 30 '21 at 02:38
2

When you import @pdftron/webviewer some code is running even though you haven't called the WebViewer function. The useEffect callback doesn't run in SSR. You can use Dynamic Imports there to import the module:

useEffect(() => {    
    import('@pdftron/webviewer')
     .then(WebViewer) => {
        WebViewer({
          path: "/lib",
          initialDoc: "/pdf/GustavoMorilla.pdf"
        }, viewer.current);
    }) 
}, []);
lissettdm
  • 12,267
  • 1
  • 18
  • 39
  • I admire your follow-up and attention lissettdm, the answer from dna worked! – Gustavo Morilla Mar 30 '21 at 02:40
  • 1
    Yes, I wanted to share a native solution without extra lib, also you can use 'require' if you don't want to use dynamic module, but if you are using nextjs the answer from @dna is the correct answer. – lissettdm Mar 30 '21 at 11:35
0

I kept getting 'window is not defined', the only solution that worked for me was following the NextJs way for importing external libraries dynamically:

useEffect(() => {
  const loadWebViewer = async () => {
    const WebViewer = (await import('@pdftron/webviewer')).default;
    if (viewer.current) {
      WebViewer(
        {
          path: '/lib',
          initialDoc: `/api/getPdf/${encodeURIComponent(file)}/`,
          disabledElements: [
            'viewControlsButton',
            'viewControlsOverlay',
            'toolsOverlay',
            'ribbonsDropdown',
            'selectToolButton',
            'panToolButton',
            'leftPanelButton',
            'toggleNotesButton',
            'toolsHeader',
          ],
        },
        viewer.current
      );
    }
  };
  loadWebViewer();
}, []);