Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ReferenceError: document is not defined in Next.js while working with React Aria overlays

I'm learning Next.js for web development and I came across commerce, a boilerplate for e-commerce websites written in Next.js. As I was browsing through the code I found the Sidebar component which uses React Aria for creating overlays.

I wanted to use this part in my own project, so wrote a Overlay component that also uses the OverlayContainer component.

import { useRef } from 'react';

import {
    useOverlay,
    useModal,
    OverlayContainer
} from '@react-aria/overlays';

const Overlay = ({ className, children, open = false, onClose }) => {
    const ref = useRef(null);

    const { modalProps } = useModal();

    let { overlayProps } = useOverlay({ onClose: onClose, open: open, isDismissable: true }, ref);
    return (
        <OverlayContainer>
            <div
                {...overlayProps}
                {...modalProps}
                ref={ref}
            >
                {children}
            </div>
        </OverlayContainer>

    );
};

export default Overlay;

This component gets loaded in my Layout component, just as in the commerce project. However, when I try to load up the index page, it gives me the following error:

Server Error
ReferenceError: document is not defined

This error happened while generating the page. Any console logs will be displayed in the terminal window.
Source
pages/_document.tsx (90:33) @ Function.getInitialProps

  88 |     }
  89 | 
> 90 |     const { html, head } = await ctx.renderPage({ enhanceApp })
     |                                 ^
  91 |     const styles = [...flush()]
  92 |     return { html, head, styles }
  93 |   }

When I remove the OverlayContainer component, it loads all fine. I tried updating my dependencies, comparing more code to the Github repo, but nothing found so far.

What's the problem here? And how could I fix it? I'm using Next 10 with React 17.0.1.

like image 971
Bas Avatar asked Nov 15 '22 03:11

Bas


2 Answers

A workaround that you can do is isBrowser which is fairly common for NextJS apps.

const isBrowser = typeof window !== "undefined";

Use it to conditionally render your OverlayContainer.

import { useRef } from "react";

import { useOverlay, useModal, OverlayContainer } from "@react-aria/overlays";

/**
 * Utility to detect if you're on the server, or in the browser.
 */
const isBrowser = typeof window !== "undefined";

const Overlay = ({ className, children, open = false, onClose }) => {
  const ref = useRef(null);

  const { modalProps } = useModal();

  let { overlayProps } = useOverlay(
    { onClose: onClose, open: open, isDismissable: true },
    ref
  );
  return isBrowser ? (
    <OverlayContainer>
      <div {...overlayProps} {...modalProps} ref={ref}>
        {children}
      </div>
    </OverlayContainer>
  ) : null;
};

export default Overlay;

like image 123
Kevin Wang Avatar answered Dec 27 '22 06:12

Kevin Wang


This happened because Next JS has server-side rendering. When you are using server-side rendering there is no browser. Hence, there is not any variable window or document. Hence this error shows up.

like image 21
Shivanshu Singh Avatar answered Dec 27 '22 08:12

Shivanshu Singh